从类中打印所有变量值

时间:2009-10-06 16:58:29

标签: java reflection

我有一个类,其中包含有关人员的信息,如下所示:

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

我希望toString()为所有变量返回this.name +" - "+ this.locations + ...。我试图使用this question所示的反射来实现它,但我无法打印实例变量。

解决这个问题的正确方法是什么?

9 个答案:

答案 0 :(得分:85)

来自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();
}

答案 1 :(得分:43)

为什么当有开源已经很好地完成工作时,你想要重新发明轮子。

apache common-langsspring都支持一些非常灵活的构建器模式

对于apache,这是你如何反思地做到这一点

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

如果您只想打印您关心的字段,请按以下步骤操作。

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

您可以使用非默认ToStringStyle“打造”打印输出,甚至可以使用自己的风格进行自定义。

我没有亲自尝试弹簧ToStringCreator api,但看起来非常相似。

答案 2 :(得分:32)

如果您使用Eclipse,这应该很简单:

1.按 Alt + Shift + S

2.选择“Generate toString()...”

享受!你可以拥有toString()s的任何模板。

这也适用于getter / setter。

答案 3 :(得分:10)

Generic toString()one-liner,使用反射和样式自定义:

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);
}

答案 4 :(得分:6)

访问字段值时,传递实例而不是null。

为什么不在这里使用代码生成?例如,Eclipse将为您生成一个可重用的toString实现。

答案 5 :(得分:4)

另一种简单方法是让Lombok为您生成toString方法。

为此:

  1. 只需将Lombok添加到您的项目
  2. 即可
  3. 将注释@ToString添加到班级的定义
  4. 编译您的课程/项目,并完成
  5. 例如,在您的情况下,您的课程将如下所示:

    @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.
    }
    

    在这种情况下的输出示例:

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

    有关how to use the annotation @ToString的更多详情。

    注意:您也可以让Lombok为您生成getters and settershere是完整的功能列表。

答案 6 :(得分:1)

如果ReflectionToStringBuilder.toString()的输出对您来说不够可读,则代码为:
1)按字母顺序对字段名称进行排序 2)在行的开头标记带星号的非空字段

public static Collection<Field> getAllFields(Class<?> type) {
    TreeSet<Field> fields = new TreeSet<Field>(
            new Comparator<Field>() {
        @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);
    }
}

测试工具:

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;
}

答案 7 :(得分:0)

使用@cletus回答,您必须获取所有模型字段(上层)并设置field.setAccessible(true)以访问私有成员。以下是完整的代码段:

@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;
}

答案 8 :(得分:0)

我将得到如下答案:

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);

        }
    }

}