2016-03-07 56 views
17

jestem na rozwiązywaniu zagadek niektóre Java i natknęliśmy się na ten jeden:JDK 1.7 vs JDK 1.6 klas wewnętrzne różnicy spadków

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

Podczas kompilowania tego kodu z javac 1.6.0_45 dostaję, zgodnie z oczekiwaniami, ten błąd:

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

Wynika to kompilator generuje domyślnego konstruktora dla Inner2 klasie z podobnym kodzie, co tłumaczy błąd powyżej:

Inner2() { 
    this.super(); 
} 

I to jest oczywiste, teraz, bo naprawdę nie można tego zrobić w Java 1.6.0_45, JLS 8.8.7.1 (jak się domyślam):

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 w Odd situation for "cannot reference this before supertype constructor has been called")

Ale jeśli spróbuję skompilować go z javac 1.7.0_79 - jest OK!

Tutaj pojawia się pytanie - Co zostało zmienione w Javie 1.7, że ten kod jest teraz poprawny?

Z góry dziękuję!

+3

@EJP sprawdziłeś [zaakceptowaną odpowiedź] (http://stackoverflow.com/a/3383555/365237) tego, ponieważ ten wygląda odpowiednio – eis

+2

@EJP, również, 'this.super() 'jest ** nie ** równoważne' super() '. Jeśli spróbujesz to zrobić w nie-wewnętrznej klasie, która nie jest zagnieżdżona, otrzymasz błąd kompilacji przed [JLS1.6 8.8.7.1]. 'Jeśli S nie jest klasą wewnętrzną lub deklaracja S występuje w kontekście statycznym, to nie istnieje natychmiast załączająca instancja i względem S. Błąd kompilacji występuje, gdy wywołanie konstruktora nadklasy jest kwalifikowanym wywołaniem konstruktora klasy nadrzędnej. "Podobne do [JLS1.7 8.8.7.1]. – ar4ers

Odpowiedz

6

wygląda jakby tam była dyskusja na ten sam problem jak bug JDK-6708938: Synthetic super-constructor call should never use 'this' as a qualifier na bug trackerze Java .

Sądzę, że byłoby wspaniale, gdybyś przyjrzał się innym Pokrewnym problemom z poprzedniego, na przykład JDK-4903103: Can't compile subclasses of inner classes .

Należy zwrócić uwagę na stałe wersje obu błędów.

W rezultacie zobacz Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7.

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

I od Maintenance Review of JSR 901 (Java Language Specification) dla Java SE 7 (w wersji pełnej, strona 242, niebieski tekst) lub taka sama w The Java Language Specification, Java SE 7 Edition (tuż przed sekcją 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.

Widać więc, że część z błędem kompilacji zniknęła.

+0

Dziękuję za odpowiedź! Teraz mam wskazówkę, że coś zdecydowanie się zmieniło! Ale nie rozumiem, co dokładnie. Nie znalazłem większych różnic między 'JLS SE 7' i' JLS Third Edition' w całej sekcji 8.8. – ar4ers

+1

@ ar4ers Dodałem różnice między tymi dwiema wersjami JSL związanymi z tym problemem. – NikolayKondratyev

+0

Wielkie dzięki za dodatkowe uwagi! Teraz rozumiem różnicę. I, być może wiesz również, gdzie można znaleźć określoną definicję zachowania (np. Tworzenie konstruktów syntetycznych)? Jak mogę się domyślić - to jest JVMS, czy to prawda? – ar4ers

-1

Podejrzewam, że ma do czynienia z invoke dynamic który został dodany w Javie 1.7 przygotowania do lambda jest w Javie 8.

+0

Sprawdziłem to na pierwszym miejscu. Niestety, nie jest. Użyłem 'javap -c' na wszystkich trzech plikach' .class', 'Outer.class',' Outer $ Inner1.class' oraz 'Outer $ Inner2.class'.Brak dowodów "invokedynamic", tylko "invokespecial" i "putfield". Obecnie badam ten problem, ale nie mam jeszcze wyniku. – ar4ers