17

I'm on solving some Java puzzles and stumbled on this one:

public class Outer {
    class Inner1 extends Outer {}
    class Inner2 extends Inner1 {}
}

While compiling this code with javac 1.6.0_45 I'm getting, as expected, this error:

Outer.java:8: cannot reference this before supertype constructor has been called
class Inner2 extends Inner1 {}                                                                                                
^

This is because of compiler generates default constructor for Inner2 class with similar code, which explains error above:

Inner2 () {
    this.super();
}

And it's obvious now, because you really can't do this in Java 1.6.0_45, JLS 8.8.7.1 (as I can guess):

An explicit constructor invocation statement in a constructor body may not refer to any instance variables or instance methods declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.

See (accepted answer in Odd situation for "cannot reference this before supertype constructor has been called")

But if I try to compile it with javac 1.7.0_79 - it is OK!

And here goes the question - What has been changed in Java 1.7, that this code is now correct?

Thanks in advance!

Community
  • 1
  • 1
ar4ers
  • 740
  • 5
  • 19
  • 3
    @EJP did you check the [accepted answer](http://stackoverflow.com/a/3383555/365237) of that one, as that one does look relevant – eis Mar 08 '16 at 11:22
  • 2
    @EJP, also, `this.super()` is **not** equivalent to `super()`. If you try to do this in non-inner non-nested class you will get a compile-time error, prior to [JLS1.6 8.8.7.1]. `If S is not an inner class, or if the declaration of S occurs in a static context, no immediately enclosing instance of i with respect to S exists. A compiletime error occurs if the superclass constructor invocation is a qualified superclass constructor invocation.` Similar to [JLS1.7 8.8.7.1]. – ar4ers Mar 08 '16 at 21:30

2 Answers2

6

Looks like there was discussion of the same problem as the bug JDK-6708938: Synthetic super-constructor call should never use 'this' as a qualifier on the Java bug tracker.

Also I think it would be great for you to take a look at other Related issues of previous one, for example JDK-4903103: Can't compile subclasses of inner classes .

Notice the Fixed Versions of both bugs.

And as the result see Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7.

From The Java Language Specification Third Edition

Otherwise, S is an inner member class (§8.5). It is a compile-time error if S is not a member of a lexically enclosing class, or of a superclass or superinterface thereof. 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 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.

And from Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7 (full version, page 242, blue text) or the same in The Java Language Specification, Java SE 7 Edition (just before section 8.8.8)

Otherwise, S is an inner member class (§8.5).

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 you can see that the part with compile-time error has gone.

Nikolay K
  • 3,770
  • 3
  • 25
  • 37
  • Thank you for your reply! Now I have a clue that something definitely has been changed! But I don't understand what exactly. I didn't find any major differences between `JLS SE 7` and `JLS Third Edition` in whole 8.8 section. – ar4ers Mar 09 '16 at 20:06
  • 1
    @ar4ers I have added the differences of these two versions of JSL related to the issue. – Nikolay K Mar 10 '16 at 02:41
  • Big thank you for your additional notes! Now I understand the difference. And, may be you also know, where can specific behavior definition(like synthetic constructor creation) be found? As I can guess - it is JVMS, am I getting it right? – ar4ers Mar 12 '16 at 14:20
  • 1
    @ar4ers I guess you can find it in both JLS (more compiler specific) and JVMS (more runtime specific). If you want to read them you can find them at [Java Language and Virtual Machine Specifications page](http://docs.oracle.com/javase/specs/) – Nikolay K Mar 12 '16 at 14:56
-1

I suspect that is has to do with invoke dynamic which was added in java 1.7 to prepare for the lambda's in java 8.

Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
  • I'v checked it in the first place. Sadly, it is not. I used `javap -c` on all three `.class` files, `Outer.class`, `Outer$Inner1.class` and `Outer$Inner2.class`. No evidence of `invokedynamic`, only `invokespecial` and `putfield`. I'm currently on investigation of this problem, but no result yet. – ar4ers Mar 08 '16 at 18:12