2015-05-07 6 views
5

Folgendes wird nicht kompilieren:Kann nicht innere Klasse von einem statischen Kontext verweisen, sondern nur dann, wenn äußere Klasse generic

class Outer<T> { 
    class Inner { 

    } 

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

Wenn ich jedoch <T> entfernen, es kompiliert. Warum die Inkonsistenz?

Auch, wenn ich sage Outer.Inner inner;, anstelle von Inner inner;, kompiliert es. Wieder, warum die Inkonsistenz?

Ich würde einen Fehler in allen Fällen oder keinen erwarten. Könnte jemand erklären, was vor sich geht?

+2

Nun, Sie könnten "T" in "Inner", z. eine Mitgliedsvariable Wie würde "Nested" etwas über den Typ wissen, wenn "Outer" generisch ist? –

+1

Ändern Sie diese Zeile in "Outer .Inner innere;" oder eine andere Spezialisierung von 'T' –

Antwort

4

Warum die Inkonsistenz?

Ich würde sagen, das ist überhaupt keine Inkonsistenz. Dies ist im Grunde ein Problem des Verständnisses von Generika. Betrachten Sie den folgenden Code (Ihr geänderten Code):

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

    static class Nested { 
     Inner inner; 
    } 
} 

In diesem obigen Beispiel ist ähnlich zu dem, was Sie geschrieben haben, habe ich eine neue Variable t vom Typ T hinzugefügt, die die Generika von Outer Klasse in der Klasse Inner. Nun würde in diesem obigen Beispiel nicht kompiliert werden, da in der Klasse Inner ein nicht-statischer oder Laufzeitverweis vorhanden ist. Wenn Sie also Inner in einer statischen Klasse Nested deklarieren, kennt der JAVA-Compiler den Typ T, der nur deklariert wird in der Laufzeit, so erhalten Sie einen Fehler. Aber in Ihrem Fall haben Sie nichts dergleichen getan, aber der Compiler weiß nicht, ob so etwas vorhanden ist oder nicht. So gibt es den Fehler.

Jetzt im zweiten Fall haben Sie die generische T aus der Klassendeklaration der Outer entfernt. Es gibt also keine Möglichkeit, die Variable t in der Klasse Inner zu deklarieren, so dass kein Fehler auftritt.

Im dritten Fall haben Sie Outer.Inner für den Typ der Variablen inner deklariert und es erfolgreich kompiliert.Hier betrachtete der Compiler Outer als RAW TYPE. Aber diese Art von Rohtyp-Deklarationen sollte vermieden werden. So wäre es besser zu schreiben:

Outer<?>.Inner inner; 

Hier Java-Compiler halten Outer jedes Objekt als Parameter zu nehmen, die Object erben würde.

+0

Sie denken, dass Sie alles über innere Klassen und Generika gelernt haben, aber dann stoßen Sie auf etwas wie das ... Ich frage mich, welche andere seltsame Interaktion ich vermisst habe. Schöne Erklärung! – Lii

1
class OuterClass { 

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

Eine verschachtelte Klasse ist ein Mitglied ihrer einschließenden Klasse. Nicht statische geschachtelte Klassen (innere Klassen) haben Zugriff auf andere Mitglieder der einschließenden Klasse, selbst wenn sie als privat deklariert sind. Statisch verschachtelte Klassen haben keinen Zugriff auf andere Member der umschließenden Klasse.

Wie bei Klassenmethoden und Variablen ist eine statische verschachtelte Klasse mit ihrer äußeren Klasse verknüpft. Und wie statische Klassenmethoden kann eine statische verschachtelte Klasse nicht direkt auf Instanzvariablen oder Methoden verweisen, die in ihrer einschließenden Klasse definiert sind: Sie kann sie nur über eine Objektreferenz verwenden.

Statische verschachtelte Klassen werden mit dem Namen umschließenden Klasse zugegriffen:

OuterClass.StaticNestedClass 

Zum Beispiel ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie folgende Syntax:

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

Weitere Informationen finden Sie die unten klicken:

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

+2

Schöne Erklärung der inneren und statischen Klassen, aber es erklärt nicht das Problem in der Frage. – Lii

Verwandte Themen