Generic toString Method for Simple Java Beans
I have seen developers writing toString method in each of their bean class. The purpose is to print the bean variables for logging or debugging purposes. I thought of reducing their effort by writing a generic toString method to have in their base bean class. It works for simple bean classes. Its no-brainer you can modify to work for others.
public String toString() { String lineSeaparator = System.getProperty("line.separator"); StringBuffer buffer = new StringBuffer(lineSeaparator); buffer.append("|---------"); buffer.append(this.getClass()); buffer.append("---------|"); buffer.append(lineSeaparator); Method[] methods = this.getClass().getMethods(); if(methods != null && methods.length >0){ Method method = null; for(int i =0; i< methods.length; i++){ method = methods[i]; if(method.getName().startsWith("get") && !method.getName().startsWith("getClass")){ buffer.append (method.getName().replaceAll("get","")); buffer.append(" = "); Object[] params=null; try { buffer.append (method.invoke(this, params)); } catch (Exception e) { buffer.append(" "); } buffer.append(lineSeaparator); } } } buffer.append("|------------------------|"); buffer.append(lineSeaparator); return buffer.toString(); }
Any suggestions to improve are welcome.
Does this method print only the variable names or variable names + values?
From the code, I think it prints only variable names. Is it correct?
It prints the values too. We are invoking the getter method using the reflection
method.invoke(this, params)
which returns the value.
Now I get it! :-)
Nice code snippet. But it does not work with boolean properties.
This is how you can add boolean props:
for (int i = 0; i < methods.length; i++) {
method = methods[i];
final String methodName = method.getName();
final boolean isBooleanProp = methodName.startsWith(“is”);
if ((methodName.startsWith(“get”) || isBooleanProp) && !method.getName().startsWith(“getClass”)) {
buffer.append(method.getName().replaceAll(isBooleanProp ? “is” : “get”, “”));
buffer.append(” = “);
Object[] params = null;
try {
buffer.append(method.invoke(this, params));
} catch (Exception e) {
buffer.append(” “);
}
buffer.append(lineSeaparator);
}
}
Hello Thejesh.
I wanted to thank you for this posting as it is very helpful.
As I was implementing it I thought of a possible improvement and would love to know your thoughts. By using java.lang.reflect.Field the logic may become simpler and the code more robust:
.
..
…
Field[] fields = this.getClass().getDeclaredFields();
if (fields != null && fields.length > 0) {
Field field = null;
for (int i =0; i < fields.length; i++) {
field = fields[i];
field.setAccessible(true);
buffer.append(field.getName());
buffer.append(" = ");
try {
buffer.append(field.get(this));
} catch (Exception e) {
buffer.append(" ");
}
buffer.append(lineSeparator);
}
}
…
..
.
This should also take care of all booleans as well.
Thoughts?
Hello Thej
BeanUtils offers a describe API that can convert a bean to readable String format.toString() can be overridden to return as
BeanUtils.describe(this).toString();
Hello
below code more specific
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
try {
BeanInfo info = Introspector.getBeanInfo(this.getClass());
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (int i = 0; i < props.length; i++) {
PropertyDescriptor prop = props[i];
if (!prop.getName().equals("class")) {
String data = prop.getName() + "="
+ prop.getReadMethod().invoke(this, null);
if (i < props.length – 1) {
stringBuffer.append(data + "\n");
}
if (i == props.length – 1) {
stringBuffer.append(data);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringBuffer.toString();
}