4

The following code compiles as expected:

class A {
    class B {}
    class C extends B {}
}

But, if we have class B extend class A, we receive a compilation error:

class A {
    class B extends A {}
    class C extends B {}  // <-- Error here
}
No enclosing instance of type A is available due to some intermediate 
constructor invocation.

What is happening here? Why does extending A change anything?

EDIT: Apparently, this compiles fine in Java 7. I would appreciate an explanation as to why it did not compile in older Java versions and what was changed in Java 7 to allow for it.


SEE ALSO:

arshajii
  • 127,459
  • 24
  • 238
  • 287
  • Please forget about the whole piece of nonsense - this is a bug. Javac works fine in this case. I've edited my answer. https://bugs.eclipse.org/bugs/show_bug.cgi?id=373371 – zw324 Jun 13 '13 at 14:29
  • @ZiyaoWei This also does not work in IntelliJ – arshajii Jun 13 '13 at 14:34
  • Javac 7 should work, and if not, adding the constructor does help. – zw324 Jun 13 '13 at 14:35
  • Dupe found - http://stackoverflow.com/questions/3383460/odd-situation-for-cannot-reference-this-before-supertype-constructor-has-been-c, but the case has changed since, so I am not marking this as a dupe. Still trying to find related information. – zw324 Jun 13 '13 at 15:02
  • Found the reference from JLS 7, see my edited answer. – zw324 Jun 13 '13 at 15:45

2 Answers2

5

Since B is not static, it needs some instance of A to be able to exist, thus the error.

If B is static, the error goes away.

Ah, forget about the nonsense. It is a bug, and it works on ideone in Java7 mode. However, prior to Java 7 it does not work - see this question, and you need to either

  1. Change B to static

  2. Add a constructor

    C() {
        A.this.super();
    }
    

And then it will be working.

The reason why this happens before Java 7 might be the following which is from JLS:

Let C be the class being instantiated, let S be the direct superclass of C, and let i be the instance being created.

The implicit super is called on the immediately enclosing instance of i with respect to S.

In the earlier JLS, the immediately enclosing instance is defined as

Let O be the innermost lexically enclosing class of which S is a member, and let n be an integer such that O is the nth lexically enclosing class of C. The immediately enclosing instance of i with respect to S is the nth lexically enclosing instance of this.

However, in Java 7:

Let O be the innermost lexically enclosing class of S, and let n be an integer such that O is the n'th lexically enclosing class of C.

The immediately enclosing instance of i with respect to S is the n'th lexically enclosing instance of this.

So in the past it was the innermost lexically enclosing class of which S is a member while now it is the innermost lexically enclosing class of S, so it changed from C to A, thus the code works in Java 7.

Community
  • 1
  • 1
zw324
  • 26,764
  • 16
  • 85
  • 118
  • The second is like calling itself again which will cause it to call itself infinitely. Recursively. – johk95 Jun 13 '13 at 14:19
0

It's a recursion.
If B extends A, and A has a new B in itself, so that B will extend A again, and so on...

As mentioned by @ZiyaoWei the error goes away when B is static. That's because then the class B will only exist one time.

johk95
  • 873
  • 10
  • 28