2015-05-07 5 views
5

Quanto segue non verrà compilato:non può fare riferimento classe interna da un contesto statico, ma solo se la classe esterna è generico

class Outer<T> { 
    class Inner { 

    } 

    static class Nested { 
     Inner inner; // Error: Outer.this cannot be referenced from a static context 
    } 
} 

Tuttavia, se tolgo <T>, si compila. Perché l'incoerenza?

Inoltre, se dico Outer.Inner inner;, anziché Inner inner;, viene compilato. Ancora una volta, perché l'incoerenza?

Mi aspetterei un errore in tutti i casi o nessuno. Qualcuno potrebbe spiegare cosa sta succedendo?

+2

Bene, è possibile fare riferimento a 'T' in' Interno', ad es. una variabile membro. In che modo 'Nested' sa qualcosa sul tipo di quello se" Outer "è generico? –

+1

Cambia quella linea in 'Esterno . Interno interno;' o qualche altra specializzazione di 'T' –

risposta

4

Perché l'incoerenza?

Direi che non è affatto incoerenza. Questo è fondamentalmente un problema di comprensione dei generici. Si consideri il seguente codice (Il tuo codice modificato):

class Outer<T> { 
    class Inner{ 
     T t;//Added this extra line 
    } 

    static class Nested { 
     Inner inner; 
    } 
} 

In questo esempio di cui sopra è in qualche modo simile a quello che hai scritto solo ho aggiunto una variabile nuova t di tipo T che è i generici di Outer classe nella classe Inner. Ora in questo esempio sopra non verrebbe compilato perché nella classe Inner esiste un riferimento non statico o di runtime, pertanto, quando si dichiara Inner in una classe statica Nested, il compattatore JAVA non conosce il tipo di T, che viene dichiarato solo nel runtime, in modo da ottenere un errore. Ma nel tuo caso non hai fatto nulla del genere ma il compilatore non sa se qualcosa del genere sia presente o meno. Quindi dà l'errore.

Ora nel secondo caso è stato rimosso il generico T dalla dichiarazione di classe dello Outer. Quindi non esiste la possibilità di dichiarare la variabile t nella classe Inner quindi non c'è alcun errore.

Nel terzo caso è stato dichiarato Outer.Inner per il tipo di variabile inner ed è stato compilato correttamente.Qui il compilatore considera Outer come RAW TYPE. Ma questo tipo di dichiarazioni di tipo grezzo dovrebbe essere evitato. Quindi sarebbe meglio scrivere:

Outer<?>.Inner inner; 

Qui Java compilatore considera Outer di prendere qualsiasi oggetto come parametri che avrebbero ereditato Object.

+0

Pensi di aver imparato tutto su classi interiori e generici ma poi ti imbatti in qualcosa del genere ... Mi chiedo quale altra strana interazione mi sia sfuggita. Bella spiegazione! – Lii

1
class OuterClass { 

    ... 
    static class StaticNestedClass { 
     ... 
    } 
    class InnerClass { 
     ... 
    } 
} 

Una classe nidificata è un membro della classe di inclusione. Le classi nidificate non statiche (classi interne) hanno accesso ad altri membri della classe che li include, anche se sono dichiarate private. Le classi nidificate statiche non hanno accesso ad altri membri della classe che li include.

Static Nested Classes 

Come con i metodi e le variabili di classe, una classe innestata statica è associata con la sua classe esterna. E come i metodi di classi statiche, una classe nidificata statica non può fare riferimento direttamente alle variabili di istanza o ai metodi definiti nella sua classe di inclusione: può usarli solo attraverso un riferimento a un oggetto.

classi annidate statiche sono accessibili usando il nome della classe di inclusione:

OuterClass.StaticNestedClass 

Ad esempio, per creare un oggetto per la classe innestata statica, utilizzare la seguente sintassi:

OuterClass.StaticNestedClass nestedObject = 
new OuterClass.StaticNestedClass(); 

Per ulteriori informazioni, vedere il sottostante cliccare:

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

+2

Bella spiegazione delle classi interne e statiche, ma non spiega il problema nella domanda. – Lii