1

I have been trying to create a robust code that prints out any Java class for debugging. For that, I use reflections. In order to protect against recursive definition such as "Boolean contains static final Boolean TRUE", I ignore fields equal to their parents. I use String += just out of laziness. It doesn't have to be efficient.

Yet, is there a nicer way to do recursive description of objects with reflections?

public String reflectionShowFields(Object parentObject) {
    String stringData = "";

    for (Field field:parentObject.getClass().getFields()) {
        try {
            Class<?> type = field.getType();
            String typeSimpleName = type.getSimpleName();
            Object fieldValue = field.get(parentObject);
            String fieldName = field.getName();
            if (type.isPrimitive() || type.isEnum() || CharSequence.class.isAssignableFrom(type)) {
                stringData += String.format("%s: %s\n", fieldName, fieldValue);
            } else if (Iterable.class.isAssignableFrom(type)) {
                stringData += String.format(">>> %s[%s]: \n", fieldName, typeSimpleName);
                for (Object item:(Iterable)fieldValue) {
                    stringData += reflectionShowFields(item);
                }
                stringData += String.format("<<< %s[%s]: \n", fieldName, typeSimpleName);
            } else if (!fieldValue.equals(parentObject)) {
                stringData += String.format(">>> %s[%s]: %s \n--------\n", fieldName, typeSimpleName, fieldValue.toString());
                stringData+= reflectionShowFields(fieldValue);
                stringData += String.format("<<< %s[%s]: \n", fieldName, typeSimpleName);
            }
        } catch (IllegalAccessException ignored) {}
    }
    return stringData;
}
mipe34
  • 5,596
  • 3
  • 26
  • 38
Meymann
  • 2,520
  • 2
  • 28
  • 22
  • 2
    Can't eclipse generate a toString() for you? This seems like more trouble than it's worth. – Rob Feb 19 '13 at 15:43
  • See also [Auto-generating toString Method](http://stackoverflow.com/questions/2653268/auto-generating-tostring-method) – Vadzim Dec 06 '13 at 18:50

2 Answers2

4

You could use Apache commons-lang ReflectionToStringBuilder https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html

CupawnTae
  • 14,192
  • 3
  • 29
  • 60
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • Could have worked if I could easily join libs :( I am running Android so I have to be thin on libs and thin on footprint. Since the whole thing is for debugging, I better not waste precious memory when the final product doesn't need it. Thanks. S.M – Meymann Mar 03 '13 at 09:22
2

I don't think this is going to work.

  • Ignoring fields "that are equal to their parents" won't work. What if you have an A that refers to a B that refers back to the A.

  • You want to know about the cycles, and also the shared nodes in a DAG.

  • Iterating an Iterable can have side-effects, or it might never terminate, or it might throw exceptions.

  • Producing a readable rendering of an arbitrary graph is likely to really hard.

  • This is going to be an order of magnitude slower than a hand-built toString() method.

But think about it this way. If this was a good idea, there would be high profile 3rd-party libraries that did this kind of thing. And we'd all be using them already. It turns out that there ARE 3rd-party libraries, but you'd hardly call them high profile.


Incidentally, you could use JAXB or a JSON binding to render your POJOs as text. That achieves the same ends ...


Finally, your example of Boolean with a static field of type Boolean is not apropos. You wouldn't want to render static fields when displaying an instance.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Agree, had to fix it so that it works. Had to give up recursive types. If you have a recursive type that doesn't define toString() - tough luck. It's a pity but I didn't want to put too much time on debug tools. As for 3rd parties etc. I prefer not. I am a lib so I better not mess the user with other libs. Also, it's Android. I need to be memory skinny. So for me, it's only POJO. – Meymann Mar 03 '13 at 09:16