什么是循环引用
循环引用(Cyclic Reference)是指在数据结构(如对象、类或模块)中,两个或多个元素相互引用,形成一个闭环。
带来的问题
这种情况在编程中可能导致内存泄漏、解析过程无限循环或其他问题
解析过程触发无限循环
public void bug(){
// 数据 mock
Node node = mock();
// 解析触发死循环
Parsed parse = parse(node);
}
private Node mock() {
Node node = new Node();
Node node1 = new Node();
node.value = node1;
node.name = "node";
node1.value = node;
node1.name = "node1";
return node;
}
class Node {
Node value;
String name;
}
class Parsed {
Parsed value;
String name;
}
private Parsed parse(Node node) {
int i = node.hashCode();
Parsed result = new Parsed();
result.value = parse(node.value);
result.name = node.name;
return result;
}
解决方案
public void test(){
// 数据 mock
Node node = mock();
// 解析
Parsed parse = parse(node, new HashMap<>());
}
private Node mock() {
Node node = new Node();
Node node1 = new Node();
node.value = node1;
node.name = "node";
node1.value = node;
node1.name = "node1";
return node;
}
class Node {
Node value;
String name;
}
class Parsed {
Parsed value;
String name;
}
private Parsed parse(Node node, HashMap<Integer, Parsed> cache) {
int i = node.hashCode();
Parsed result = null;
// 通过缓存记录解析结果,
// 如果被解析对象已经被解析过了,则直接引用,避免陷入无限循环
if (cache.containsKey(i)) {
result = cache.get(i);
} else {
result = new Parsed();
cache.put(i, result);
result.name = node.name;
result.value = parse(node.value,cache);
}
return result;
}