使用Java类反射的通用“quasi toString()”

时间:2013-02-19 15:41:01

标签: java reflection

我一直在尝试创建一个强大的代码,可以打印出任何用于调试的Java类。为此,我使用反射。 为了防止递归定义,例如"布尔包含静态最终布尔值TRUE",我忽略等于其父项的字段。 我只是出于懒惰而使用String + =。它不一定非常有效。

然而,有没有更好的方法来对具有反射的对象进行递归描述?

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

2 个答案:

答案 0 :(得分:4)

答案 1 :(得分:2)

我不认为这会起作用。

  • 忽略“等于其父母”的字段将无效。如果您的A引用了引用B的{​​{1}},该怎么办?

  • 希望了解周期以及DAG中的共享节点。

  • 迭代A可能会产生副作用,或者它可能永远不会终止,或者它可能会引发异常。

  • 生成任意图形的可读渲染可能非常困难。

  • 这比手工制作的Iterable方法慢一个数量级。

但是这样考虑一下。如果这是一个好主意,那么会有高调的第三方库来做这种事情。我们都已经在使用它们了。事实证明,有第三方图书馆,但你很难称之为高调。


顺便说一句,您可以使用JAXB或JSON绑定将POJO呈现为文本。这达到了同样的目的......


最后,你的布尔值示例与布尔类型的静态字段不合适。在显示实例时,您不希望呈现静态字段。