我一直在尝试创建一个健壮的代码,可以打印出任何Java类进行调试。为此,我使用反射。为了防止递归定义,例如"布尔包含静态最终布尔 TRUE",我忽略了等于其父级的字段。我使用字符串 += 只是出于懒惰。它不一定是有效的。
然而,有没有更好的方法来对带有反射的对象进行递归描述?
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: %sn", 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;
}
使用 Apache commons-lang ReflectionToStringBuilder https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html
这是行不通的。
忽略"等于其父级"的字段是行不通的。 如果您有引用回
A
的B
的A
怎么办。您希望了解周期以及 DAG 中的共享节点。
迭代
Iterable
可能会产生副作用,或者可能永远不会终止,或者可能会引发异常。生成任意图形的可读渲染可能非常困难。
这将比手工构建的
toString()
方法慢一个数量级。
但这样想吧。 如果这是一个好主意,那么会有备受瞩目的第三方库来做这种事情。 我们都已经在使用它们了。 事实证明,有第 3 方库,但您几乎不会称它们为高调。
顺便说一下,您可以使用 JAXB 或 JSON 绑定将 POJO 呈现为文本。 这达到了相同的目的...
最后,您不建议使用布尔类型的静态字段的布尔示例。 您不希望在显示实例时呈现静态字段。