2016-03-07 13 views
17

Ich bin einige Java-Rätsel auf die Lösung und stolperte über dieses:JDK 1.7 vs JDK 1.6 inneren Klassen Vererbung Unterschied

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

Während diesen Code mit javac 1.6.0_45 Kompilieren erhalte ich, wie erwartet, dieser Fehler:

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

dies wegen der Compiler erzeugt Default Konstruktor für Klasse Inner2 mit ähnlichem Code, der Fehler, der oben erklärt:

Inner2() { 
    this.super(); 
} 

Und es ist jetzt offensichtlich, weil Sie wirklich diese in Java nicht kann 1.6.0_45, JLS 8.8.7.1 (wie ich kann mir denken):

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

Aber wenn ich versuche, es mit javac 1.7.0_79 zu kompilieren - es ist OK!

Und hier geht die Frage - Was wurde in Java 1.7 geändert, dass dieser Code jetzt korrekt ist?

Vielen Dank im Voraus!

+3

@EJP hast du die [akzeptierte Antwort] (http://stackoverflow.com/a/3383555/365237) von diesem überprüft, da diese Seite relevant aussieht – eis

+2

@EJP, auch this.super() 'ist ** nicht ** äquivalent zu' super() '. Wenn Sie dies in einer nicht-inneren nicht verschachtelten Klasse versuchen, erhalten Sie vor [JLS1.6 8.8.7.1] einen Kompilierungsfehler. Wenn S keine innere Klasse ist oder wenn die Deklaration von S in einem statischen Kontext auftritt, existiert keine unmittelbar einschließende Instanz von i in Bezug auf S. Ein Kompilierungsfehler tritt auf, wenn der Aufruf des Superklassenkonstruktors ein Aufruf eines qualifizierten Superklassenkonstruktors ist. "Ähnlich wie [JLS1.7 8.8.7.1]. – ar4ers

Antwort

6

Sieht vorzubereiten, wie es die Diskussion über das gleiche Problem wie der Bug JDK-6708938: Synthetic super-constructor call should never use 'this' as a qualifier auf dem Tracker Java Fehler war .

Auch ich denke, es wäre toll für Sie, einen Blick auf andere verwandte Probleme der vorherigen, zum Beispiel JDK-4903103: Can't compile subclasses of inner classes .

Beachten Sie die behobenen Versionen beider Bugs.

Und als Ergebnis siehe Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7.

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

Und von Maintenance Review von JSR 901 (Java Language Specification) für Java SE 7 (Vollversion, Seite 242, blauer Text) oder der gleichen in The Java Language Specification, Java SE 7 Edition (kurz vor Abschnitt 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 können Sie sehen, dass der Teil mit Kompilierzeitfehler ist verschwunden.

+0

Vielen Dank für Ihre Antwort! Jetzt habe ich eine Ahnung, dass sich etwas definitiv geändert hat! Aber ich verstehe nicht genau was. Ich fand keine großen Unterschiede zwischen "JLS SE 7" und "JLS Third Edition" im gesamten Abschnitt 8.8. – ar4ers

+1

@ ar4ers Ich habe die Unterschiede dieser beiden Versionen von JSL im Zusammenhang mit dem Problem hinzugefügt. – NikolayKondratyev

+0

Vielen Dank für Ihre zusätzlichen Notizen! Jetzt verstehe ich den Unterschied. Und vielleicht wissen Sie auch, wo eine bestimmte Verhaltensdefinition (wie die synthetische Konstrukteursschaffung) gefunden werden kann? Wie ich es erraten kann - es ist JVMS, bekomme ich es richtig? – ar4ers

-1

Ich vermute, dass hat mit invoke dynamic zu tun, die in Java 1.7 hinzugefügt wurde für die Lambda in Java 8.

+0

Ich habe es in erster Linie überprüft. Leider ist es nicht. Ich habe 'javap -c' auf allen drei' .class' Dateien, 'Outer.class',' Outer $ Inner1.class' und 'Outer $ Inner2.class' verwendet.Kein Hinweis auf "aufgerufene Dynamik", nur "Aufruf" und "Putfield". Ich bin derzeit auf der Suche nach diesem Problem, aber noch kein Ergebnis. – ar4ers

Verwandte Themen