什么是循環(huán)引用
循環(huán)引用(Cyclic Reference)是指在數(shù)據(jù)結(jié)構(gòu)(如對象、類或模塊)中,兩個或多個元素相互引用,形成一個閉環(huán)。
帶來的問題
這種情況在編程中可能導(dǎo)致內(nèi)存泄漏、解析過程無限循環(huán)或其他問題
解析過程觸發(fā)無限循環(huán)
public void bug(){
// 數(shù)據(jù) mock
Node node = mock();
// 解析觸發(fā)死循環(huán)
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(){
// 數(shù)據(jù) 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;
// 通過緩存記錄解析結(jié)果,
// 如果被解析對象已經(jīng)被解析過了,則直接引用,避免陷入無限循環(huán)
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;
}