Java 两个对象通过最终引用相互引用

Java 两个对象通过最终引用相互引用,java,constructor,final,Java,Constructor,Final,我有一个类似这样的类: public class Node { private final Node otherNode; public Node(Node otherNode) { this.otherNode = otherNode; } } 想做些像 Node n1, n2 ; n1 = new Node(n2); n2 = new Node(n1); 但显然不能,因为n2尚未初始化。我不想使用setter来设置otherNode,因为它是fin

我有一个类似这样的类:

public class Node {
    private final Node otherNode;
    public Node(Node otherNode) {
        this.otherNode = otherNode;
    }
}
想做些像

Node n1, n2 ;
n1 = new Node(n2);
n2 = new Node(n1);

但显然不能,因为n2尚未初始化。我不想使用setter来设置otherNode,因为它是final,因此应该只设置一次。实现这一点最干净的方法是什么?是否有一些我不熟悉的奇特Java语法可以让我这么做?除了构造函数(丑陋)之外,我应该使用initialize方法,还是只使用setter(丑陋)?

有第二个构造函数,它不接受参数并构造自己的
节点,将自己传递为另一个的“other”

然后在使用时:

Node n1 = new Node();
Node n2 = n1.getOther();
确保它们相互关联:

System.out.println(n1 == n1.getOther().getOther());
System.out.println(n2 == n2.getOther().getOther());
System.out.println(n1 == n2.getOther());
System.out.println(n2 == n1.getOther());
这些都是打印的
true

(这是对Gottman答案的补充。)

更通用的解决方案是编写一个构造函数,如:

private Node(final int numNodesInLoop) {
    if(numNodesInLoop < 1) {
        throw new IllegalArgumentException();
    }
    Node head = this;
    for(int i = 1; i < numNodesInLoop) {
        head = new Node(head);
    }
    this.otherNode = head;
}

(如果您以后需要另一个构造函数,无论出于何种原因,该构造函数都将采用
int
,这也是未来的证明。然后您可以修改此构造函数,使其也采用伪参数,只需告诉编译器您要用什么构造函数即可。factory方法仍具有相同的约定。)

我知道的唯一方法就是用二传手。谁先来?鸡还是蛋?私有构造函数,如果otherNode==null,则调用私有构造函数?从技术上讲,你可以通过反射来实现这一点,但我不推荐。@ruakh你如何使用反射,这与使用setter不同?@SotiriosDelimanolis:我不确定你所说的“不同于使用setter”是什么意思,但我的意思是,您可以编写类似于
final Node firstNode=new Node(null);最终节点secondNode=新节点(firstNode);final java.lang.reflect.Field otherNodeField=Node.class.getField(“otherNode”);otherNodeField.setAccessible(true);otherNodeField.set(第一个节点,第二个节点)。(奇怪的是,
setAccessible
的Javadoc没有提到它有这种效果——它只提到了它与
private
/
protected
/[default]/
public
——但是你可以试试看。)这听起来很完美!感谢当这种方法起作用时,对用户来说似乎不是很“明显”。我更喜欢显式静态方法createNodeAndOther()。至少,这个构造函数需要一些好的javadocs。@user949300:我同意;如果你发布一个演示如何创建这样一个方法的答案,我会给你一个+1。@ruakh在进一步的简要回顾后,我认为这不能用纯静态方法完成。您需要某种“特殊构造函数”和静态方法的组合,如您的答案中所示。
private Node(final int numNodesInLoop) {
    if(numNodesInLoop < 1) {
        throw new IllegalArgumentException();
    }
    Node head = this;
    for(int i = 1; i < numNodesInLoop) {
        head = new Node(head);
    }
    this.otherNode = head;
}
public static Node newNodeLoop(final int numNodes) {
    return new Node(numNodes);
}