Let's say I have a class like this (and also further assume that all the private variables:
public class Item {
private String _id = null;
private String _name = null;
private String _description = null;
...
}
Now, if I want to build a toString() representation of this class, I would do something like this inside the Item class:
@Override
public String toString() {
return (_id + " " + _name + " " + _description);
}
But what if I have say 15 private variables inside the class? Do I have to write the name of each and every variable like this?
Ideally, I would like to get over with the task by iterating through the list of private variables of this class and construct the string representation:
@Override
public String toString() {
ArrayList members = getClass().getMembers(); //Some method like this
String string = "";
for(...)
string += members[i] + " ";
}
Or perhaps a toJSON method, I would still need access to the names of these variables. Any suggestions?
解决方案
You could do:
@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();
}
Don't use string concatenation to construct an end result from 15 data members, particularly if the toString() will be called a lot. The memory fragmentation and overhead could be really high. Use StringBuilder for constructing large dynamic strings.
I usually get my IDE (IntelliJ) to simply generate toString() methods for me rather than using reflection for this.
Another interesting approach is to use the @ToString annotation from Project Lombok:
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;
}
}
}
I find this much more preferable to, say, Jakarta Commons toString builders because this approach is far more configurable and it's also built at compile-time not run-time.