【问题标题】:Printing all variables value from a class打印类中的所有变量值
【发布时间】:2010-12-04 08:27:00
【问题描述】:

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

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 所示,但我无法打印实例变量。

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

【问题讨论】:

  • 当你试图用反射来做这件事时发生了什么?它对我有用...
  • 我不知道将什么传递给 field.get()。阅读 cletus 的回答后,我了解到应该通过“this”。

标签: java reflection


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    【解决方案3】:

    既然开源已经很好地完成了这项工作,为什么还要重新发明轮子。

    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 为您的打印输出“设置样式”,甚至可以使用您自己的样式对其进行自定义。

    我没有亲自尝试过springToStringCreator api,但是看起来很相似。

    【讨论】:

    • 春天的很蹩脚,它只是样式,没有反射
    【解决方案4】:

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

    【讨论】:

    • 这对我不起作用。我的班级有私有变量和 get-set 方法
    【解决方案5】:

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

    1.按Alt+Shift+S

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

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

    这也适用于 getter/setter。

    【讨论】:

      【解决方案6】:

      加上@cletus 答案,您必须获取所有模型字段(上层)并设置field.setAccessible(true) 以访问私有成员。这是完整的 sn-p:

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

      【讨论】:

        【解决方案7】:

        另一个简单的方法是让Lombok为你生成toString方法。

        为此:

        1. 只需将Lombok 添加到您的项目中
        2. 将注释@ToString 添加到您的类的定义中
        3. 编译你的类/项目,就完成了

        例如,在您的情况下,您的课程将如下所示:

        @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是完整的功能列表。

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            我的答案如下:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-11-18
              • 2011-09-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多