gpt4 book ai didi

java - 遍历对象层次结构时将节点标记为已访问

转载 作者:行者123 更新时间:2023-12-01 04:13:06 24 4
gpt4 key购买 nike

我制作了一个小型 Java 程序,它使用反射来检查对象的字段并递归地遍历其结构,以构建其所有成员的树,类似于调试器在检查变量时所做的操作。

最大的问题是有时会出现循环引用。我的树变成了图表!然后我的程序进入无限循环并最终抛出 StackOverflow 异常(哦,讽刺!)

我的问题是......如何将任意对象“标记”为已访问以实现任何标准图横向算法?我无法使用 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);
}

}
}

最佳答案

使用哈希表数据结构,例如 HashMap,并使用对象作为键。事实上,一些哈希会发生冲突,但冲突解决是哈希表背后的根本思想:每个哈希都会导致一个包含具有相同哈希的每个键/值对的存储桶,从而允许您检索对象。

但是,如果您的对象还重新实现了 equals() 以便两个对象可能相等,那就是一个问题,因为冲突解决方法将无法区分同一存储桶中的两个键。如果是这样,请设计自己的哈希表,使用 hashcode() 获取哈希值,但使用语言“==”比较来按内存地址比较对象。

关于java - 遍历对象层次结构时将节点标记为已访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19710512/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com