Java toString() using reflection?

后端 未结 7 1601
梦如初夏
梦如初夏 2020-12-02 18:30

I was writing a toString() for a class in Java the other day by manually writing out each element of the class to a String and it occurred to me that using reflection it mig

相关标签:
7条回答
  • 2020-12-02 18:33

    Not reflection, but I had a look at generating the toString method (along with equals/hashCode) as a post-compilation step using bytecode manipulation. Results were mixed.

    0 讨论(0)
  • 2020-12-02 18:35

    Another option, if you are ok with JSON, is Google's GSON library.

    public String toString() {
        return new GsonBuilder().setPrettyPrinting().create().toJson(this);
    }
    

    It's going to do the reflection for you. This produces a nice, easy to read JSON file. Easy-to-read being relative, non tech folks might find the JSON intimidating.

    You could make the GSONBuilder a member variable too, if you don't want to new it up every time.

    If you have data that can't be printed (like a stream) or data you just don't want to print, you can just add @Expose tags to the attributes you want to print and then use the following line.

     new GsonBuilder()
    .setPrettyPrinting()
    .excludeFieldsWithoutExposeAnnotation()
    .create()
    .toJson(this);
    
    0 讨论(0)
  • 2020-12-02 18:36

    Apache commons-lang ReflectionToStringBuilder does this for you.

    import org.apache.commons.lang3.builder.ReflectionToStringBuilder
    
    // your code goes here
    
    public String toString() {
       return ReflectionToStringBuilder.toString(this);
    }
    
    0 讨论(0)
  • 2020-12-02 18:37

    Here is the Netbeans equivalent to Olivier's answer; smart-codegen plugin for Netbeans.

    0 讨论(0)
  • 2020-12-02 18:44

    You can use already implemented libraries, as ReflectionToStringBuilder from Apache commons-lang. As was mentioned.

    Or write smt similar by yourself with reflection API.

    Here is some example:

    class UniversalAnalyzer {
    
       private ArrayList<Object> visited = new ArrayList<Object>();
    
       /**
        * Converts an object to a string representation that lists all fields.
        * @param obj an object
        * @return a string with the object's class name and all field names and
        * values
        */
       public String toString(Object obj) {
          if (obj == null) return "null";
          if (visited.contains(obj)) return "...";
          visited.add(obj);
          Class cl = obj.getClass();
          if (cl == String.class) return (String) obj;
          if (cl.isArray()) {
             String r = cl.getComponentType() + "[]{";
             for (int i = 0; i < Array.getLength(obj); i++) {
                if (i > 0) r += ",";
                Object val = Array.get(obj, i);
                if (cl.getComponentType().isPrimitive()) r += val;
                else r += toString(val);
             }
             return r + "}";
          }
    
          String r = cl.getName();
          // inspect the fields of this class and all superclasses
          do {
             r += "[";
             Field[] fields = cl.getDeclaredFields();
             AccessibleObject.setAccessible(fields, true);
             // get the names and values of all fields
             for (Field f : fields) {
                if (!Modifier.isStatic(f.getModifiers())) {
                   if (!r.endsWith("[")) r += ",";
                   r += f.getName() + "=";
                   try {
                      Class t = f.getType();
                      Object val = f.get(obj);
                      if (t.isPrimitive()) r += val;
                      else r += toString(val);
                   } catch (Exception e) {
                      e.printStackTrace();
                   }
                }
             }
             r += "]";
             cl = cl.getSuperclass();
          } while (cl != null);
    
          return r;
       }    
    }
    
    0 讨论(0)
  • 2020-12-02 18:55

    W/reflection, as I hadn't been aware of the apache library:

    (be aware that if you do this you'll probably need to deal with subobjects and make sure they print properly - in particular, arrays won't show you anything useful)

    @Override
    public String toString()
    {
        StringBuilder b = new StringBuilder("[");
        for (Field f : getClass().getFields())
        {
            if (!isStaticField(f))
            {
                try
                {
                    b.append(f.getName() + "=" + f.get(this) + " ");
                } catch (IllegalAccessException e)
                {
                    // pass, don't print
                }
            }
        }
        b.append(']');
        return b.toString();
    }
    
    
    private boolean isStaticField(Field f)
    {
        return Modifier.isStatic(f.getModifiers());
    }
    
    0 讨论(0)
提交回复
热议问题