Java 打印类中的所有变量值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1526826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 13:51:18  来源:igfitidea点击:

Printing all variables value from a class

javareflection

提问by Macarse

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 questionbut I can't manage to print instance variables.

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

What is the correct way to solve this?

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

采纳答案by cletus

From Implementing toString:

实现 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();
}

回答by Scott Stanchfield

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

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

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

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

回答by Oscar Chan

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

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

Both apache common-langsand springsupport some very flexible builder pattern

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

For apache, here is how you do it reflectively

对于 apache,这里是你如何反射性地做到这一点

@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 ToStringStyleor even customizing it with your own style.

您可以使用非默认的ToStringStyle来“设计”您的打印输出,甚至可以使用您自己的样式对其进行自定义。

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

我没有亲自尝试 spring ToStringCreatorapi,但它看起来非常相似。

回答by Stephane Chatre

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

通用 toString() 单行,使用反射和样式自定义:

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

回答by Linerd

If you are using Eclipse, this should be easy:

如果您使用的是 Eclipse,这应该很容易:

1.Press Alt+Shift+S

1.按Alt+ Shift+S

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

2.选择“生成toString()...”

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

享受!您可以拥有任何 toString() 模板。

This also works with getter/setters.

这也适用于 getter/setter。

回答by Kaidul

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:

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

回答by Nicolas Filotto

Another simple approach is to let Lombokgenerate the toStringmethod for you.

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

For this:

为了这:

  1. Simply add Lombokto your project
  2. Add the annotation @ToStringto the definition of your class
  3. Compile your class/project, and it is done
  1. 只需添加Lombok到您的项目
  2. 将注释添加@ToString到类的定义中
  3. 编译你的类/项目,就完成了

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 protected], phone=99999, fax=88888)

More details about how to use the annotation @ToString.

有关如何使用注释的@ToString更多详细信息。

NB:You can also let Lombokgenerate the getters and settersfor you, hereis the full feature list.

注意:您也可以让我们为您Lombok生成getter 和 setter是完整的功能列表。

回答by 18446744073709551615

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

如果来自的输出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);
    }
}

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

回答by gogog

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

        }
    }

}