anon
anon

Reputation:

using 'this' keyword in 'super()' constructor

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

Answers (2)

Stephen C
Stephen C

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

Eran
Eran

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

Related Questions