3

Hi I have below simple classes.

class A {
int i;
int y;

A(int i, int y)
{

}

and then when I try to do below

class B extends A
{
    B()
    {
        super(i, y);        
    }
}

I get the error saying "Cannot refer to an instance field y while explicitly invoking a constructor". I know this is wrong but I want to know why I cannot do this. Since A's constructor gets initialized first it has 0 value for both i and y and why cannot pass those values to super constructor.

Juliyanage Silva
  • 2,529
  • 1
  • 21
  • 33
  • Possible duplicate of [Why can't I refer to an instance method while explicitly invoking a constructor?](https://stackoverflow.com/questions/3685506/why-cant-i-refer-to-an-instance-method-while-explicitly-invoking-a-constructor). Did SO not hint at this question when typing your title, or does it not answer your question? – achAmháin Oct 09 '18 at 15:23
  • @achAmháin, I went through this. It's ok for instance methods. But why cant we opt out specially initializing super class instance variables. – Juliyanage Silva Oct 09 '18 at 15:26
  • @achAmháin yes this did not answer my question.. – Juliyanage Silva Oct 09 '18 at 15:28
  • Super() calls the parent to initialize the fields. You can't use them until after super. – Peter Lawrey Oct 09 '18 at 15:32
  • 1
    `A` only defines a 2 argument constructor so `B` must use it. For example: `B() { super(0, 0); }` – Andrew S Oct 09 '18 at 15:33
  • If you want to pass 0 , call `super(0, 0);` – Peter Lawrey Oct 09 '18 at 15:33
  • @PeterLawrey, before coming to explicit super(i,y) call, it will call, A's constructor and then Object class constructor. Then will be initialize all the instance variables down the class hierarchy. so at this point shouldn't i and y get initialized? – Juliyanage Silva Oct 09 '18 at 15:36
  • 1
    `super(i, y)` is attempting to call `A`'s constructor with `A.i` and `A.y`, but `A.i` and `A.y`have not yet been initialized since `A`'s constructor has not yet been called. – Andrew S Oct 09 '18 at 15:40

1 Answers1

7

Since A's constructor gets initialized first it has 0 value for both i and y and why cannot pass those values to super constructor.

The problem is that expressions for the arguments in super(i, y) (in B) are evaluated before calling the A constructor.

The execution sequence for new B() is as follows:

  1. Static initialization for B and its dependents is triggered (if this hasn't happened already).
  2. Argument expressions for B's constructor parameters are evaluated evaluated. (There aren't any, in this case.)
  3. A heap node is created, initialized with B's type, and all fields (in B and its superclasses) are default initialized.
  4. The super parameters for B are evaluated.
  5. The super parameters for A are evaluated.
  6. The Object() constructor body is executed.
  7. The fields A.i and A.y would be initialized (if they had initializers).
  8. The A(int,int) constructor body is executed.
  9. B's field initializers would be executed.
  10. The B() constructor body is executed.
  11. The reference to completed B instance is returned.

As you can see, step 4 refers to y which hasn't been initialized yet1. It won't be initialized until step 7.

Note: the above is simplified. Refer to JLS 15.9.4 for the full specification.


1 - The rules don't take account of the fact that there is no initializer in your example. But that's a good thing. 1) Taking account of that would make them more complicated and ... surprising. 2) What is the utility of allowing access to a variable if you know it has the default value? You could just use that value directly!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    This is the body of the no-args constructor of the `java.lang.Object` class. (Probably empty.) – Stephen C Jun 07 '22 at 13:20
  • if the A's variables were static they're created before the static vars of B or after that? – John Wick Sep 14 '22 at 12:02
  • 1
    The order of creation is uninteresting: the variables are *created* (i.e. space is allocated to hold them) before they are used. The order of variable *initialization* is interesting ... but it is a different question, and *orthogonal* to this question. Read this: https://stackoverflow.com/questions/3499214 – Stephen C Sep 14 '22 at 12:10