两个对象相互引用,带有最终引用

时间:2013-05-23 23:49:28

标签: 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,因为它是最终的,因此只能设置一次。实现这一目标的最简洁方法是什么?是否有一些我不熟悉的Java语法让我这样做?我应该使用除了构造函数之外的初始化方法(丑陋),还是只使用一个setter(也很难看)?

2 个答案:

答案 0 :(得分:9)

让第二个构造函数不带参数并构造自己的Node,将自己作为另一个的“其他”传递。

public class Node
{
   private final Node otherNode;

   public Node(Node other)
   {
      otherNode = other;
   }

   public Node()
   {
      otherNode = new Node(this);
   }

   public Node getOther()
   {
      return otherNode;
   }
}

然后使用它时:

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

答案 1 :(得分:2)

(这是rgettman答案的补充。)

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

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;
}

具有两个节点的情况将被实例化为new Node(2)

根据user949300对rgettman的回答,我做了上面的private,因为Node构造函数的含义是int不太可猜测(它会创建一个循环) ?!),所以最好将它包装在名称使其功能清晰的static工厂方法中:

public static Node newNodeLoop(final int numNodes) {
    return new Node(numNodes);
}

(如果你以后需要另外一个构造函数需要int,无论出于什么原因,这也更具有前瞻性。你可以修改这个构造函数来获取一个伪参数,只是足以告诉编译器你想要什么构造函数。工厂方法仍然具有相同的契约。)