Printing all variables value from a class

JavaReflection

Java Problem Overview


I have a class with information about a Person that looks something like this:

public class Contact {
    private String name;
    private String location;
    private String address;
    private String email;
    private String phone;
    private String fax;

    public String toString() {
        // Something here
    }
    // Getters and setters.
}

I want toString() to return this.name +" - "+ this.locations + ... for all variables. I was trying to implement it using reflection as shown from this question but I can't manage to print instance variables.

What is the correct way to solve this?

Java Solutions


Solution 1 - Java

From Implementing toString:

public String toString() {
  StringBuilder result = new StringBuilder();
  String newLine = System.getProperty("line.separator");

  result.append( this.getClass().getName() );
  result.append( " Object {" );
  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();
}

Solution 2 - Java

Why do you want to reinvent the wheel when there are opensource that are already doing the job pretty nicely.

Both apache common-langs and spring support some very flexible builder pattern

For apache, here is how you do it reflectively

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

Here is how you do it if you only want to print fields that you care about.

@Override
public String toString() 
{
    return new ToStringBuilder(this)
      .append("name", name)
      .append("location", location)
      .append("address", address)
      .toString(); 
}

You can go as far as "styling" your print output with non-default ToStringStyle or even customizing it with your own style.

I didn't personally try spring ToStringCreator api, but it looks very similar.

Solution 3 - Java

If you are using Eclipse, this should be easy:

1.Press Alt+Shift+S

2.Choose "Generate toString()..."

Enjoy! You can have any template of toString()s.

This also works with getter/setters.

Solution 4 - Java

Generic toString() one-liner, using reflection and style customization:

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
...
public String toString()
{
  return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

Solution 5 - Java

When accessing the field value, pass the instance rather than null.

Why not use code generation here? Eclipse, for example, will generate a reasoble toString implementation for you.

Solution 6 - Java

Another simple approach is to let Lombok generate the toString method for you.

For this:

  1. Simply add Lombok to your project
  2. Add the annotation @ToString to the definition of your class
  3. Compile your class/project, and it is done

So for example in your case, your class would look like this:

@ToString
public class Contact {
    private String name;
    private String location;
    private String address;
    private String email;
    private String phone;
    private String fax;

    // Getters and setters.
}

Example of output in this case:

Contact(name=John, location=USA, address=SF, email=foo@bar.com, phone=99999, fax=88888)

More details about how to use the annotation @ToString.

NB: You can also let Lombok generate the getters and setters for you, here is the full feature list.

Solution 7 - Java

If the output from ReflectionToStringBuilder.toString() is not enough readable for you, here is code that:

  1. sorts field names alphabetically

  2. flags non-null fields with asterisks in the beginning of the line

    public static Collection getAllFields(Class type) { TreeSet fields = new TreeSet( new Comparator() { @Override public int compare(Field o1, Field o2) { int res = o1.getName().compareTo(o2.getName()); if (0 != res) { return res; } res = o1.getDeclaringClass().getSimpleName().compareTo(o2.getDeclaringClass().getSimpleName()); if (0 != res) { return res; } res = o1.getDeclaringClass().getName().compareTo(o2.getDeclaringClass().getName()); return res; } }); for (Class c = type; c != null; c = c.getSuperclass()) { fields.addAll(Arrays.asList(c.getDeclaredFields())); } return fields; } public static void printAllFields(Object obj) { for (Field field : getAllFields(obj.getClass())) { field.setAccessible(true); String name = field.getName(); Object value = null; try { value = field.get(obj); } catch (IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } System.out.printf("%s %s.%s = %s;\n", value==null?" ":"*", field.getDeclaringClass().getSimpleName(), name, value); } }

test harness:

public static void main(String[] args) {
	A a = new A();
	a.x = 1;
	B b = new B();
	b.x=10;
	b.y=20;
	System.out.println("=======");
	printAllFields(a);
	System.out.println("=======");
	printAllFields(b);
	System.out.println("=======");
}

class A {
	int x;
	String z = "z";
	Integer b; 
}
class B extends A {
	int y;
	private double z = 12345.6;
	public int a = 55;
}

Solution 8 - Java

Addition with @cletus answer, You have to fetch all model fields(upper hierarchy) and set field.setAccessible(true) to access private members. Here is the full snippet:

@Override
public String toString() {
    StringBuilder result = new StringBuilder();
    String newLine = System.getProperty("line.separator");

    result.append(getClass().getSimpleName());
    result.append( " {" );
    result.append(newLine);

    List<Field> fields = getAllModelFields(getClass());

    for (Field field : fields) {
        result.append("  ");
        try {
            result.append(field.getName());
            result.append(": ");
            field.setAccessible(true);
            result.append(field.get(this));
        
        } catch ( IllegalAccessException ex ) {
//                System.err.println(ex);
        }
        result.append(newLine);
    }
    result.append("}");
    result.append(newLine);

    return result.toString();
}

private List<Field> getAllModelFields(Class aClass) {
    List<Field> fields = new ArrayList<>();
    do {
        Collections.addAll(fields, aClass.getDeclaredFields());
        aClass = aClass.getSuperclass();
    } while (aClass != null);
    return fields;
}

Solution 9 - Java

i will get my answer as follow:

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class findclass {
    public static void main(String[] args) throws Exception, IllegalAccessException {
		new findclass().findclass(new Object(), "objectName");
	    new findclass().findclass(1213, "int");
        new findclass().findclass("ssdfs", "String");
    }


	public Map<String, String>map=new HashMap<String, String>();
	
	public void findclass(Object c,String name) throws IllegalArgumentException, IllegalAccessException {
		if(map.containsKey(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))){
			System.out.println(c.getClass().getSimpleName()+" "+name+" = "+map.get(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))+" = "+c);			
			return;}
		map.put(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()), name);
		Class te=c.getClass();
		if(te.equals(Integer.class)||te.equals(Double.class)||te.equals(Float.class)||te.equals(Boolean.class)||te.equals(Byte.class)||te.equals(Long.class)||te.equals(String.class)||te.equals(Character.class)){
			System.out.println(c.getClass().getSimpleName()+" "+name+" = "+c);
			return;	
		}
		
		
		if(te.isArray()){
			if(te==int[].class||te==char[].class||te==double[].class||te==float[].class||te==byte[].class||te==long[].class||te==boolean[].class){
				boolean dotflag=true;
				for (int i = 0; i < Array.getLength(c); i++) {
					System.out.println(Array.get(c, i).getClass().getSimpleName()+" "+name+"["+i+"] = "+Array.get(c, i));
				}
				return;	
			}
			Object[]arr=(Object[])c;
			for (Object object : arr) {
				if(object==null)	
					System.out.println(c.getClass().getSimpleName()+" "+name+" = null");
				else {
					findclass(object, name+"."+object.getClass().getSimpleName());
				}
			}
			
			
		}	
			
		Field[] fields=c.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
	
			if(field.get(c)==null){
				System.out.println(field.getType().getSimpleName()+" "+name+"."+field.getName()+" = null");
				continue;
			}
			
			findclass(field.get(c),name+"."+field.getName());
		}
		if(te.getSuperclass()==Number.class||te.getSuperclass()==Object.class||te.getSuperclass()==null)
			return;
		Field[]faFields=c.getClass().getSuperclass().getDeclaredFields();
		
		for (Field field : faFields) {
			field.setAccessible(true);
				if(field.get(c)==null){
					System.out.println(field.getType().getSimpleName()+" "+name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName()+" = null");
					continue;
				}
				Object check=field.get(c);
				findclass(field.get(c),name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName());

		}
		
	}
	
	public void findclass(Object c,String name,Writer writer) throws IllegalArgumentException, IllegalAccessException, IOException {
		if(map.containsKey(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))){
			writer.append(c.getClass().getSimpleName()+" "+name+" = "+map.get(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))+" = "+c+"\n");			
			return;}
		map.put(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()), name);
		Class te=c.getClass();
		if(te.equals(Integer.class)||te.equals(Double.class)||te.equals(Float.class)||te.equals(Boolean.class)||te.equals(Byte.class)||te.equals(Long.class)||te.equals(String.class)||te.equals(Character.class)){
			writer.append(c.getClass().getSimpleName()+" "+name+" = "+c+"\n");
			return;	
		}
		
		
		if(te.isArray()){
			if(te==int[].class||te==char[].class||te==double[].class||te==float[].class||te==byte[].class||te==long[].class||te==boolean[].class){
				boolean dotflag=true;
				for (int i = 0; i < Array.getLength(c); i++) {
					writer.append(Array.get(c, i).getClass().getSimpleName()+" "+name+"["+i+"] = "+Array.get(c, i)+"\n");
				}
				return;	
			}
			Object[]arr=(Object[])c;
			for (Object object : arr) {
				if(object==null){	
					writer.append(c.getClass().getSimpleName()+" "+name+" = null"+"\n");
				}else {
					findclass(object, name+"."+object.getClass().getSimpleName(),writer);
				}
			}
			
			
		}	
			
		Field[] fields=c.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
	
			if(field.get(c)==null){
				writer.append(field.getType().getSimpleName()+" "+name+"."+field.getName()+" = null"+"\n");
				continue;
			}
			
			findclass(field.get(c),name+"."+field.getName(),writer);
		}
		if(te.getSuperclass()==Number.class||te.getSuperclass()==Object.class||te.getSuperclass()==null)
			return;
		Field[]faFields=c.getClass().getSuperclass().getDeclaredFields();
		
		for (Field field : faFields) {
			field.setAccessible(true);
				if(field.get(c)==null){
					writer.append(field.getType().getSimpleName()+" "+name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName()+" = null"+"\n");
					continue;
				}
				Object check=field.get(c);
				findclass(field.get(c),name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName(),writer);

		}
	}
	
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMacarseView Question on Stackoverflow
Solution 1 - JavacletusView Answer on Stackoverflow
Solution 2 - JavaOscar ChanView Answer on Stackoverflow
Solution 3 - JavaLinerdView Answer on Stackoverflow
Solution 4 - JavaStephane ChatreView Answer on Stackoverflow
Solution 5 - JavaScott StanchfieldView Answer on Stackoverflow
Solution 6 - JavaNicolas FilottoView Answer on Stackoverflow
Solution 7 - Java18446744073709551615View Answer on Stackoverflow
Solution 8 - JavaKaidulView Answer on Stackoverflow
Solution 9 - JavagogogView Answer on Stackoverflow