2015-05-07 22 views
5

Następujące nie skompilować:nie może odwoływać się od wewnętrznej klasy statycznej kontekście, ale tylko wtedy, gdy klasa zewnętrzna jest nazwą rodzajową

class Outer<T> { 
    class Inner { 

    } 

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

Jednak jeśli usunąć <T>, kompiluje. Skąd ta niekonsekwencja?

Również, jeśli powiem Outer.Inner inner;, zamiast Inner inner;, kompiluje. Ponownie, dlaczego niespójność?

Spodziewam się błędu we wszystkich przypadkach lub nie wystąpi. Czy ktoś mógłby wyjaśnić, co się dzieje?

+2

Cóż, możesz odwołać się do 'T' w' Inner', np. zmienna składowa. W jaki sposób 'Nested' może wiedzieć cokolwiek na temat tego, czy' Outer' jest ogólny? –

+1

Zmień linię na 'Zewnętrzna . Wewnętrzna wewnętrzna;' lub inna specjalizacja 'T' –

Odpowiedz

4

Dlaczego ta niespójność?

Powiedziałbym, że to nie jest żadna niekonsekwencja. Zasadniczo jest to problem zrozumienia generyków. Rozważmy następujący kod (swój kod zmodyfikowany):

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

    static class Nested { 
     Inner inner; 
    } 
} 

W tym powyższym przykładzie jest nieco podobny do tego, co zostało napisane tylko dodałem nową zmienną t typu T który jest generyków Outer klasie w klasie Inner. W tym przykładzie powyższy przykład nie zostałby skompilowany, ponieważ w klasie Inner znajduje się odniesienie niestatyczne lub wykonawcze, więc po zadeklarowaniu Inner w klasie statycznej Nested kompilator JAVA nie zna typu T, który jest tylko zadeklarowany. w środowisku wykonawczym, więc pojawia się błąd. Ale w twoim przypadku nie zrobiłeś nic takiego, ale nadal kompilator nie wie, czy coś takiego jest obecne, czy nie. Więc daje błąd.

Teraz w drugim przypadku usunięto ogólny T z deklaracji klasy Outer. Tak więc nie ma możliwości zadeklarowania zmiennej t w klasie , więc nie ma błędu.

W trzecim przypadku zadeklarowano Outer.Inner dla typu zmiennej inner i została ona pomyślnie skompilowana.Tutaj kompilator uznał RAW TYPU RAW TYPU. Należy jednak unikać tego rodzaju deklaracji typu surowego. Więc lepiej byłoby napisać:

Outer<?>.Inner inner; 

Tutaj kompilator Java uważa Outer wziąć dowolny obiekt jako parametry, które dziedziczą Object.

+0

Myślisz, że nauczyłeś się wszystkiego na temat klas wewnętrznych i generycznych, ale potem natknąłeś się na coś takiego ... Zastanawiam się, jaką inną dziwną interakcję przegapiłem. Ładne wyjaśnienie! – Lii

1
class OuterClass { 

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

Klasa zagnieżdżona jest członkiem swojej klasy otaczającej. Niestatyczne klasy zagnieżdżone (klasy wewnętrzne) mają dostęp do innych elementów klasy otaczającej, nawet jeśli są zadeklarowane jako prywatne. Statyczne klasy zagnieżdżone nie mają dostępu do innych elementów klasy otaczającej.

Static Nested Classes 

Podobnie jak w przypadku metod i zmiennych klas, statyczna klasa zagnieżdżona jest powiązana z jej klasą zewnętrzną. Podobnie jak w przypadku metod klasy statycznej, klasa zagnieżdżona statyczna nie może odwoływać się bezpośrednio do zmiennych instancji lub metod zdefiniowanych w klasie otaczającej: może używać ich tylko poprzez odwołanie do obiektu.

Statyczne klasy zagnieżdżone są dostępne za pomocą nazwy klasy zakrywające:

OuterClass.StaticNestedClass 

Na przykład, aby utworzyć obiekt dla statycznego pod-klasy, należy użyć następującej składni:

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

Więcej informacji można znaleźć kliknij poniżej:

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

+2

Ładne wyjaśnienie klas wewnętrznych i statycznych, ale nie wyjaśnia problemu w pytaniu. – Lii