共享多个 class 用于 ToString 实现

Shared multiple class for ToString implementation

我有多个 pojo classes 使用下面的代码。

public class ToStringImpl {

public String toString(){
      StringBuilder result = new StringBuilder();
      String newLine = "\n";


      result.append( this.getClass().getName() );
      result.append( " Data {" );
      result.append(newLine);

      //determine fields declared in this class only (no fields of superclass)
      Field[] fields = this.getClass().getDeclaredFields();

      //print field names paired with their values
      for ( Field field : fields  ) {
        result.append("  ");
        try {
          result.append( field.getName() );
          result.append(": ");
          //requires access to private field:
          result.append( field.get(this) );
        } catch ( IllegalAccessException ex ) {
          System.out.println(ex);
        }
        result.append(newLine);
      }
      result.append("}");

      return result.toString();
}

}

我如何从不同的 class 调用上面的 class? 假设我有 pojo classes 称为客户、商店、库存

public class Customer {

private String name;
private String address;

...getter...setter...

public String toString(){

    ToStringImpl log = new ToStringImpl();
    //how do I pass different classes here?
    return log.toString();
}

}

public class Store {

private String logo;
private String type;

....getter...setter...
}

public class Inventory {

private boolean isAvailable;
private long index;

...getter...setter
}

对于每个 class 我如何传递不同的 class?或者是否有更好的方法来做到这一点?或者创建 toString 作为接口并在每个 class 中实现它并将其作为构造函数传递会更好吗?

当您重写一个方法时,例如 Object#toString(),您只重写那个 class。您可以执行以下操作之一:

  • 将您的 toString() 添加到每个可能需要它的 class 中,然后只需在该对象的任何位置调用 toString() 即可。 (不推荐)
  • 在您想要的每个 class 上扩展您的 ToStringImpl 并在对象上调用 toString()。
  • 使 ToStringImpl#toString() 静态化并传递一个对象作为参数(推荐),例如:

    public static void objectToString(Object ob){
       //your code here, just replace "this" with "ob"
    }
    

您可以做的是使 ToStringImpl class 中的 toString() 方法静态化。不过我不会叫它 toString(),改成 getClassString()

示例

public static String getClassString(Object o)
{
    StringBuilder result = new StringBuilder();
    String newLine = "\n";

    result.append(o.getClass().getName());
    result.append(" Data {");
    result.append(newLine);

    // determine fields declared in this class only (no fields of
    // superclass)
    Field[] fields = o.getClass().getDeclaredFields();

    // print field names paired with their values
    for (Field field : fields)
    {
        result.append("  ");
        try
        {
            result.append(field.getName());
            result.append(": ");
            // requires access to private field:
            result.append(field.get(o));
        }
        catch (IllegalAccessException ex)
        {
            System.out.println(ex);
        }
        result.append(newLine);
    }
    result.append("}");

    return result.toString();
}

然后在你的 POJO classes 中,调用它:

public String toString()
{
    // how do I pass different classes here?
    // by passing the 'this' reference
    return ToStringImpl.getClassString(this);
}

已经有一个图书馆可以做到这一点。在 apache-commons 库中查找 ToStringBuilder,您的域对象的 toString 方法如下所示:

@Override public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

在我看来,最好的计划是删除本地代码并放入 apache-commons,或者使用 Project Lombok。如果您必须重新发明这个轮子,那么复制 ToStringBuilder 的使用静态方法的示例并将要打印的对象作为参数是合理的。

ToStringBuilder 包含一项功能,可让您限制打印哪些字段,为了您自己的理智,您自己的代码应该做类似的事情。 toString 方法用于打印出用于调试和记录的信息。如果你只是得到所有的字段,比如你发布的代码,它会在你每次在日志条目中调用 toString 时转储出整个对象的内容,你会有一些不可读的东西,它会填满你的日志并减慢你的应用程序编写所有这些信息。

您是这里信息的消费者,让它变得有用而不是让人不知所措。