使toString() 的创建自动化

  参与大项目的开发人员通常要花数个小时编写有用的toString方法。即便不为每个类都提供属于它们自己的toString方法,但每个数据容器都必须有自己的toString方法。让每个开发人员按他们自己的方法编写toString方法可能会造成混乱;每个开发人员无疑都会提出一种唯一的格式。结果,在调试过程中使用这样的输出将增添不必要的麻烦,而且也没有什么好处。因此,每个项目都应该为toString方法规定一种单一的格式,并使它们的创建自动化。
  使toString的创建自动化
  我下面将演示一个实用程序,您可用它来实现toString的自动创建。这个工具会自动为指定的类生成一个规则的、强健的toString方法,几乎消除了用于开发该方法的时间。它还对toString()的格式进行集中管理。如果您更改了格式,则必须重新生成toString方法;但是,这仍然比手动更改成百上千个类要容易得多。
  对生成的代码进行维护也很容易。如果您在类中添加了更多的属性,则您也可能需要对toString方法作一些修改。因为toString方法是自动生成的,所以您只须再次对该类运行这个实用程序来完成更改。这比手动方法更简单,而且犯错误的可能性也较小。
  代码
  本文无意解释Reflection API;下面的代码假定您已理解Reflection的基本概念。要查看Reflection API的文档,您可以访问参考资源部分。实用程序的源代码如下所示:
  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();//检索超类
  output("StringBuffer buffer=new StringBuffer(500);");//构造缓冲区
  if(cSuper!=null&&cSuper!=Object.class){
  output("buffer.append(super.toString());");//超类的toString()
  }
  for(int j=0;j<fields.length;j++){
  output("buffer.append(\""+fields[j].getName()+"=\");");//附加域名称
  if(fields[j].getType().isPrimitive()||fields[j].getType()==String.class)//检查基本数据类型或字符串类型
  output("buffer.append(this."+fields[j].getName()+");");//附加基本数据类型域的值
  else
  {
  /*它“不是”基本数据类型域,所以需要检查聚集对象的NULL值*/
  output("if(this."+fields[j].getName()+"!=null)");
  output("buffer.append(this."+fields[j].getName()+".toString());");
  output("else buffer.append(\"value is null\");");
  }//else结束
  }//循环结束
  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控制台就很满意,他们可以利用控制台手动将这些代码复制或嵌入实际的文件中。我将这些选择权留给您,本文只使用最简单的方法:system.out语句。
  这种方法的局限性
  这种方法有两个明显的局限性。第一个局限性是它不支持对象的循环包含。如果对象A包含对象B的一个引用,对象B又包含对象A的一个引用,则这个工具无法处理。但是,对于许多项目而言,这种情况很少出现。
  第二个局限性是添加或减少成员变量之后要求重新生成toString方法。因为不管用不用这个工具都需要完成这一步,所以这不是工具特有的问题。
  小结
  在本文中,我说明了一个小型的自动实用程序,它可以真正提高开发人员的效率,就整个项目的工期而言,它起着很小但很重要的作用。