Reputation:
I want to use this
in super
constructor, but there is no way to call this
before calling supertype
constructor.
I have got 3 classes. I will describe my exact problem using an example.
public class A {
C c;
A(C c) {
this.c = c;
}
}
public class B extends A {
B(C c) {
super(new C(this)); // error
}
}
public class C {
A a;
C(A a) {
this.a = a;
}
}
Upvotes: 2
Views: 272
Reputation: 718886
The problem is that you are passing the this
reference to something else before the instance has been constructed. If this was allowed, the C
constructor would be given an reference to a partial B
object. That would break abstraction for B
.
The section of the JLS that talks about this is 8.8.7.1. It says:
An explicit constructor invocation statement in a constructor body may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.
I understand the problem, but I am asking, how to solve it. I need class C to have its "owner" from when it is created but I also need class A to "own" it from beginning.
You must pass the B
reference to the C
instance after constructing B
; i.e. by assigning a new value to C.b
, directly or via a method call such as a setter. There is no way around this. Java doesn't provide a way to create objects AND make them into a cycle in a constructor chain.
One way to hide the cycle creation is to use the Builder Design Pattern. But a setter call or equivalent has to happen behind the scenes.
Note that if your a
and c
fields are both declared as final
, then there is no pure Java solution at all. (You could use some "nasty" reflection to modify one of the final
variables. Or possibly some trickery with object deserialization.)
Upvotes: 7
Reputation: 393851
You can use a parameter-less constructor to construct the C
instance, and then use a setter to set the instance variable.
public class A {
C c;
A(C c) {
this.c = c;
c.setA(this);
}
}
public class B extends A {
B(C c) {
super(new C());
}
}
public class C {
A a;
C() {
}
public void setA(A a) {
this.a = a;
}
}
Upvotes: 4