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<String> 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.