tags:

views:

269

answers:

3

Let's say I have two classes, named A and B, that are associated with each other such that it is most convenient if each class's object contains a reference to the other. In other words, class A has a variable "b" of class B. Class B has a variable "a" of class A. This way, the code in each class has easy access to the other class.

Is there any way to set up this association to be "final"? i.e. variable b in class A is final and variable a in class B is final? It seems that setting up these references in a constructor (as would be required by the final keyword) requires an illogical circular sort of reference.

This is more of a conceptual question than a practical one. Thanks!

+6  A: 

As another poster pointed out, it is possible to do this by making one of the classes responsible for constructing the other and passing itself into the constructor for the other object.

However, this lends itself to potential issues if you want one instance of the first class to correspond to one instance of the second class (which it seems you do). Another object could potentially pass an existing reference to the first class into the constructor for the second class, thus allowing an invalid situation (the an instance of the second class now has a reference to an instance of the first class which references a different instance of the second class).

More potential issues arise when you consider that the second class' constructor cannot reference uninitialized members of the first class.

My suggestion is that if the two classes are so interrelated that you want them to each have final references to the other, just make them the same class. Then you've always got a final reference to the other object: this.

Imagist
+5  A: 

Yes it is possible, if one of the class is responsible for creating the instance of the other class. The first constructor can pass an instance of itself as a parameter for the second class.

public class A {
    final B b;
    public A() {
     b = new B(this);
    }
    public B getB() {
     return b;
    }
}
public class B {
    final A a;
    public B(A a) {
     this.a = a;
    }
}
msell
While this approach may work, it is probably dangerous as B constructor is receiving a reference to a not-yet-fully-constructed element. Assume, for example, that A had another field that is initialized *after* 'b', and that B constructor tries to access it. It will get an uninitialized object. The same goes for calling methods of A from B constructor, or if A is later extended... Maybe a redesign would be a better option.
David Rodríguez - dribeas
Slightly more concise is to have one class an inner class of the other. (Note: As you made the `B` constructor public, another class in another package could construct another `B` for any instance of `A` (or `null`!).)
Tom Hawtin - tackline
Perhaps the best way would be to make both constructors package scope, and provide some sort of factory method to provide A. That way no-one can accidentally misuse the classes.
extraneon
A: 

if you use a Di container such as guice, you can acieve this without obvious reference passing inside the constructor - which may be error-prone as pointed out before.

declare dependency a-b and b-a and inject one of them in another class. guice will do some magic to allow both fields to be final. basically it will inject one proxy first and set its delegator later.

do you need a code sample for this?

Andreas Petersson