2016-03-07 16 views
17

Sono a risolvere alcuni enigmi Java e ci siamo imbattuti su questo:JDK 1.7 vs JDK 1.6 classi interne differenza eredità

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

Durante la compilazione di questo codice con javac 1.6.0_45 sto ottenendo, come previsto, questo errore:

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

Questo è causa di compilatore genera costruttore predefinito per Inner2 classe con codice simile, il che spiega l'errore sopra:

Inner2() { 
    this.super(); 
} 

Ed è ovvio ora, perché davvero non si può fare questo in Java 1.6.0_45, JLS 8.8.7.1 (posso immaginare):

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

Ma se provo a compilarlo con javac 1.7.0_79 - è OK!

E qui va la domanda - Che cosa è stato modificato in Java 1.7, che questo codice è ora corretto?

Grazie in anticipo!

+3

@EJP hai controllato la [risposta accettata] (http://stackoverflow.com/a/3383555/365237) di quella, come quella che sembra rilevante – eis

+2

@EJP, anche, 'this.super() 'è ** non ** equivalente a' super() '. Se provi a farlo in una classe non nidificata non interna, otterrai un errore in fase di compilazione, prima di [JLS1.6 8.8.7.1]. 'Se S non è una classe interna, o se la dichiarazione di S si verifica in un contesto statico, non esiste alcuna istanza di I che racchiude immediatamente rispetto a S. Si verifica un errore di compilazione se la chiamata del costruttore della superclasse è una chiamata del costruttore della superclasse qualificata. Simile a [JLS1.7 8.8.7.1]. – ar4ers

risposta

6

Sembra che si è discusso dello stesso problema come il bug JDK-6708938: Synthetic super-constructor call should never use 'this' as a qualifier sul bug tracker Java lambda .

Inoltre, penso che sarebbe bello per voi dare un'occhiata ad altri problemi correlati del precedente, ad esempio JDK-4903103: Can't compile subclasses of inner classes .

Notare le versioni fisse di entrambi i bug.

E come risultato vedere Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7.

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

E da manutenzione Rassegna di JSR 901 (Java Language Specification) per Java SE 7 (versione completa, pagina 242, il testo blu) o lo stesso in The Java Language Specification, Java SE 7 Edition (appena prima della sezione 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.

Quindi è possibile vedere che la parte con errore di compilazione è andata.

+0

Grazie per la risposta! Ora ho la certezza che qualcosa è stato sicuramente cambiato! Ma non capisco esattamente cosa. Non ho riscontrato differenze significative tra 'JLS SE 7' e' JLS Third Edition' nella sezione intera 8.8. – ar4ers

+1

@ ar4ers Ho aggiunto le differenze tra queste due versioni di JSL relative al problema. – NikolayKondratyev

+0

Grazie mille per le tue note aggiuntive! Ora capisco la differenza. E, potresti anche sapere, dove può essere trovata una specifica definizione di comportamento (come la creazione di un costruttore sintetico)? Come posso immaginare - è JVMS, sto facendo bene? – ar4ers

-1

Ho il sospetto che si ha a che fare con invoke dynamic che è stata aggiunta in Java 1.7 per preparare del Java 8.

+0

L'ho controllato in primo luogo. Purtroppo, non lo è. Ho usato 'javap -c' su tutti e tre i file' .class', 'Outer.class',' Outer $ Inner1.class' e 'Outer $ Inner2.class'.Nessuna prova di 'invokedynamic', solo' invokespecial' e 'putfield'. Sono attualmente in fase di indagine su questo problema, ma nessun risultato ancora. – ar4ers

Problemi correlati