toString methods. Even if each class doesn't get its own toString method, each data container class will. Allowing each developer to write toString his or her own way can lead to chaos; each developer will undoubtedly come up with a unique format. As a result, using the
output during debugging becomes more difficult than necessary with no obvious benefit. Therefore, each project should standardize
on a single format for toString methods and then automate their creation.toString method for a specified class, almost eliminating the time spent developing the method. It also centralizes the toString() format. If you change the format, you must regenerate the toString methods; however, this is still much easier than manually changing hundreds or thousands of classes. Maintaining the generated code is easy, too. If you add more attributes in the classes, you may be required to make the changes
in the toString method also. Since the generation of toString methods is automated, you need only run the utility on the class again to make your changes. This is simpler and less error-prone
than the manual approach.
package fareed.publications.utilities;
import java.lang.reflect.*;
public class ToStringGenerator
{
public static void main(String[] args)
{
if (args.length == 0)
{
System.out.println("Provide the class name as the command line argument");
System.exit(0);
}
try {
Class targetClass = Class.forName(args[0]);
if (!targetClass.isPrimitive() && targetClass != String.class)
{
Field fields[] = targetClass.getDeclaredFields();
Class cSuper = targetClass.getSuperclass(); // Retrieving the super class
output("StringBuffer buffer = new StringBuffer(500);"); // Buffer Construction
if (cSuper != null && cSuper != Object.class) {
output("buffer.append(super.toString());"); // Super class's toString()
}
for (int j = 0; j < fields.length; j++) {
output("buffer.append(\"" + fields[j].getName() + " = \");"); // Append Field name
if (fields[j].getType().isPrimitive() || fields[j].getType() == String.class) // Check for a primitive or string
output("buffer.append(this." + fields[j].getName() + ");"); // Append the primitive field value
else
{
/* It is NOT a primitive field so this requires a check for the NULL value for the aggregated object */
output("if ( this." + fields[j].getName() + "!= null )" );
output("buffer.append(this." + fields[j].getName() + ".toString());");
output("else buffer.append(\"value is null\"); ");
} // end of else
} // end of for loop
output("return buffer.toString();");
}
} catch (ClassNotFoundException e) {
System.out.println("Class not found in the class path");
System.exit(0);
}
}
private static void output(String data)
{
System.out.println(data);
}
}
system.out console, which allows them to copy and embed the code in the actual file manually. I simply leave those options to you and
use the simplest method: system.out statements.There are two important limitations to this approach. The first is that it doesn't support objects containing cycles. If object A contains a reference to object B, which then contains a reference to object A, this tool won't work. However, that case will be rare for many projects.