리플렉션을 사용하여 객체의 필드를 검사하고 구조를 가로 질러 재귀 적으로 구조를 가로 지르는 작은 Java 프로그램을 만들었습니다. 디버거가 검사 할 때와 비슷하게 모든 멤버의 트리를 작성합니다 변하기 쉬운.오브젝트 hirearchy 변환시 방문 노드 표시
큰 문제는 순환 참조가 나타나는 경우입니다. 내 나무가 그래프가됩니다! 그럼 내 프로그램은 무한 루프에 입력하고 결국 StackOverflow 예외를 던졌습니다 (오, 아이러니!)
내 질문은 ... 어떻게 임의의 표준 그래프 transversal 알고리즘을 구현하기 위해 방문한 임의의 개체를 "표시"할 수 있습니까? 모든 객체가 입력으로 사용될 수 있고 다른 객체가 동일한 해시 코드를 반환 할 수 있기 때문에 hashCode()를 사용할 수 없습니다. 어떤 단서?
고맙습니다.
public class ClassHierarchyItem {
private boolean parent;
private String id;
private String parentId;
private String name;
private String type;
private String value;
public ClassHierarchyItem(boolean parent, String id, String parentId, String name, String type, String value){
this.parent = parent;
this.id = id;
this.parentId = parentId;
this.name = name;
this.type = type;
this.value = value;
}
public String toString() {
return (isParent() ? "+" : "") + name + " - " + type + " - " + value + " [id=" + id + ", pId=" + parentId + "]";
}
//Getters and setters follow (cutted)
}
public class ClassHierarchyNavigator {
public static void main(String[] args) {
Integer i = 123;
// Fails with StackOverflow exception (some reference inside Integer points back to base object)
System.out.println(renderHirearchy(i));
}
public static List<ClassHierarchyItem> renderHirearchy(Object o) {
List<ClassHierarchyItem> items = new ArrayList<ClassHierarchyItem>();
boolean parent = (o.getClass().getDeclaredFields().length > 0 && !o.getClass().isPrimitive() && o.getClass() != String.class)
|| o.getClass().isArray();
buildObjectTree(items, o, parent, "root", o.getClass().getName(), "r", "");
return items;
}
private static boolean isParent(Field field) {
return (field.getClass().getDeclaredFields().length > 0 && !field.getType().isPrimitive() && field.getType() != String.class)
|| field.getType().isArray();
}
private static void buildObjectTree(List<ClassHierarchyItem> items, Object object, boolean parent,
String objectName, String objectType, String objectId, String parentId) {
long subItemCount = 1;
String value = object == null ? "null" : object.toString();
ClassHierarchyItem item = new ClassHierarchyItem(parent, objectId, parentId, objectName, objectType,
value.substring(0, value.length() > 80 ? 80 : value.length()));
items.add(item);
if (!parent) {
return;
}
// if (isArray) {
// do_array_treatment
// } else {
for (Field field : object.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object child;
try {
child = field.get(object);
} catch (IllegalArgumentException e) {
continue;
} catch (IllegalAccessException e) {
continue;
}
String childId = objectId + "-" + subItemCount++;
String fieldName = field.getName();
boolean childIsParent = child != null && !"this$0".equals(fieldName) && isParent(field);
buildObjectTree(items, child, childIsParent, fieldName, field.getType().getName(), childId, objectId);
}
}
}
검사 된 필드를 저장하는 곳의 코드입니다. –
있습니다. 코드를 업로드했습니다. 이것은 단지 사전 알파 테스트 버전입니다! 빠르고 지저분한 코드입니다! – shandrio