Java:获取类的属性以构造字符串表示

Leg*_*end 21 java reflection class tostring class-variables

假设我有一个这样的类(并且还假设所有私有变量:

public class Item {
    private String _id = null;
    private String _name = null;
    private String _description = null;

        ...
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我想构建这个类的toString()表示,我会在Item类中做这样的事情:

@Override
public String toString() {
    return (_id + " " + _name + " " + _description);
}
Run Code Online (Sandbox Code Playgroud)

但是如果我在课堂上说15个私有变量呢?我是否必须像这样写出每个变量的名称?

理想情况下,我想通过遍历此类的私有变量列表并构造字符串表示来完成任务:

@Override
public String toString() {
    ArrayList<String> members = getClass().getMembers(); //Some method like this
    String string = "";
    for(...)
        string += members[i] + " ";
}
Run Code Online (Sandbox Code Playgroud)

或者也许是一个toJSON方法,我仍然需要访问这些变量的名称.有什么建议?

cle*_*tus 35

你可以这样做:

@Override
public String toString() {
  StringBuilder sb = new StringBuilder();
  sb.append(getClass().getName());
  sb.append(": ");
  for (Field f : getClass().getDeclaredFields()) {
    sb.append(f.getName());
    sb.append("=");
    sb.append(f.get(this));
    sb.append(", ");
  }
  return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

不要使用字符串连接来构造来自15个数据成员的最终结果,特别是如果toString()要调用它们.内存碎片和开销可能非常高.使用StringBuilder构建大动态的字符串.

我通常得到我的IDE(IntelliJ)来简单地toString()为我生成方法而不是使用反射.

另一个有趣的方法是使用Project Lombok中@ToString注释:

import lombok.ToString;

@ToString(excludes="id")
public class ToStringExample {
  private static final int STATIC_VAR = 10;
  private String name;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;

  @ToString(callSuper=true, includeFieldNames=true)
  public static class Square extends Shape {
    private final int width, height;

    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我发现这比Jakarta Commons toString构建器要好得多,因为这种方法更易于配置,而且它也是在编译时而不是运行时构建的.


Bhu*_*ale 8

检查这个API org.apache.commons.lang.builder.ToStringBuilder,它提供了多种方法来创建toString使用反射或不反射.看看其他子类.

  • 谢谢。这看起来很有趣。尤其是不使用反射的方法。 (2认同)

Ste*_*ine 5

有一个这样的api,它叫做Java Reflection

要完成您的要求,您可以执行以下操作:

 Class<?> cls = this.getClass();
 Field fieldlist[] = cls.getDeclaredFields();
 for (Field aFieldlist : fieldlist) {
   // build toString output with StringBuilder()
 }
Run Code Online (Sandbox Code Playgroud)