Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

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

2 Answers

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.)

like image 193
Stephen C Avatar answered Dec 16 '25 19:12

Stephen C


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;
    }
}
like image 39
Eran Avatar answered Dec 16 '25 19:12

Eran



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!