class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Chociaż nie jest możliwy dostęp do pola statycznego za pomocą OuterClass.InnerClass.i
, jeśli chcę zarejestrować coś, co powinno być statyczne, np. Liczbę utworzonych obiektów InnerClass, pomocne byłoby uczynienie tego pola statycznym. Dlaczego więc Java zabrania statycznych pól / metod w klasach wewnętrznych?
EDYCJA: Wiem, jak sprawić, by kompilator był zadowolony ze statycznej klasy zagnieżdżonej (lub statycznej klasy wewnętrznej), ale chcę wiedzieć, dlaczego java zabrania statycznych pól / metod wewnątrz klas wewnętrznych (lub zwykłej klasy wewnętrznej) zarówno z projektu języka, jak i aspekty wdrożeniowe, jeśli ktoś wie o tym więcej.
java
inner-classes
static-members
Jichao
źródło
źródło
Odpowiedzi:
Ideą klas wewnętrznych jest działanie w kontekście otaczającej instancji. W jakiś sposób zezwalanie na statyczne zmienne i metody zaprzecza tej motywacji?
źródło
Ponieważ te klasy wewnętrzne są klasami wewnętrznymi „instancji”. Oznacza to, że są one jak atrybut instancji otaczającego obiektu.
Ponieważ są to klasy „instancji”, nie ma sensu zezwalać na
static
funkcje, ponieważstatic
ma działać bez instancji.To tak, jakbyś próbował jednocześnie utworzyć atrybut static / instance.
Weźmy następujący przykład:
class Employee { public String name; }
Jeśli utworzysz dwie instancje pracownika:
Employee a = new Employee(); a.name = "Oscar"; Employee b = new Employee(); b.name = "jcyang";
Oczywiste jest, dlaczego każdy ma swoją wartość dla nieruchomości
name
, prawda?To samo dzieje się z klasą wewnętrzną; każda instancja klasy wewnętrznej jest niezależna od drugiej instancji klasy wewnętrznej.
Więc jeśli spróbujesz utworzyć
counter
atrybut klasy, nie ma możliwości udostępnienia tej wartości w dwóch różnych instancjach.class Employee { public String name; class InnerData { static count; // ??? count of which ? a or b? } }
Podczas tworzenia instancji
a
orazb
w powyższym przykładzie, co byłoby poprawne wartości dla zmiennej statycznejcount
? Nie można tego określić, ponieważ istnienieInnerData
klasy zależy całkowicie od każdego z otaczających obiektów.Dlatego, gdy klasa jest zadeklarowana jako
static
, nie potrzebuje już żywej instancji, aby sama żyć. Teraz, gdy nie ma żadnej zależności, możesz swobodnie zadeklarować atrybut statyczny.Wydaje mi się, że brzmi to powtarzalnie, ale jeśli pomyślisz o różnicach między atrybutami instancji a atrybutami klas, będzie to miało sens.
źródło
final
pól statycznych w klasie wewnętrznej w Javie jest dozwolone. Jak wyjaśnisz ten scenariusz?InnerClass
nie może miećstatic
członków, ponieważ należy do instancji (zOuterClass
). Jeśli zadeklarujeszInnerClass
jakstatic
odłączyć go od instancji, Twój kod zostanie skompilowany.class OuterClass { static class InnerClass { static int i = 100; // no compile error static void f() { } // no compile error } }
BTW: nadal będziesz mógł tworzyć wystąpienia
InnerClass
.static
w tym kontekście pozwala na to bez otaczającej instancjiOuterClass
.źródło
InnerClass
nie nie należą doOuterClass
, przypadki z nim zrobić. Same dwie klasy nie mają takiego związku. Pytanie, dlaczego nie można mieć metod statycznych,InnerClass
wciąż jest aktualne.W rzeczywistości możesz zadeklarować pola statyczne, jeśli są stałymi i zostały zapisane w czasie kompilacji.
class OuterClass { void foo() { class Inner{ static final int a = 5; // fine static final String s = "hello"; // fine static final Object o = new Object(); // compile error, because cannot be written during compilation } } }
źródło
Ponieważ klasy wewnętrzne są zależne od wystąpienia klasy otaczającej / Outer, dlatego klasa Outer musi zostać zainicjowana przed inicjalizacją klasy Inner.
To jest JLS mówi o inicjalizacji klas. Chodzi nam o to, że klasa T zostanie zainicjowana, jeśli
Więc jeśli klasa wewnętrzna ma dostęp do pola statycznego, co spowoduje zainicjowanie klasy wewnętrznej, ale nie zapewni, że klasa otaczająca zostanie zainicjowana.
Naruszyłoby to kilka podstawowych zasad . możesz przejść do ostatniej sekcji (do
two cases
), aby uniknąć rzeczy noobówJedną z rzeczy jest to , że gdy niektórzy będą zachowywać się tak jak normalna klasa pod każdym względem i jest to związane z klasą Outer.
static nested
class
nested class
static
Ale pojęcie
Inner class
/ czy to będzie związane z klasą zewnętrzną / otaczającą. Uwaga związana z instancją, a nie klasą. Teraz skojarzenie z instancją wyraźnie oznacza, że ( z koncepcji zmiennej instancji ) będzie istnieć wewnątrz instancji i będzie się różnić między instancjami.non-static
nested class
instance
Teraz, kiedy zrobimy coś statycznego, spodziewamy się, że zostanie on zainicjowany podczas ładowania klasy i powinien być udostępniony wszystkim instancjom. Ale ze względu na to, że są niestatyczne, nawet same klasy wewnętrzne (na razie możesz zdecydowanie zapomnieć o wystąpieniu klasy wewnętrznej ) nie są współdzielone z wszystkimi wystąpieniami klasy zewnętrznej / otaczającej ( przynajmniej koncepcyjnie ), więc jak możemy się spodziewać, że jakaś zmienna klasy wewnętrznej zostaną podzielone między wszystkie wystąpienia klasy wewnętrznej.
Więc jeśli Java pozwala nam używać statycznej zmiennej wewnątrz nie statycznej klasy zagnieżdżonej. będą dwa przypadki .
context of instance
(zmienna instancji). W takim razie NIE.źródło
Oto motywacja, którą uważam za najbardziej odpowiednią dla tego „ograniczenia”: Możesz zaimplementować zachowanie statycznego pola klasy wewnętrznej jako pole instancji obiektu zewnętrznego; Więc nie trzeba statycznych pól / metod . Chodzi mi o to, że wszystkie instancje klasy wewnętrznej jakiegoś obiektu współużytkują pole (lub metodę).
Więc załóżmy, że chcesz policzyć wszystkie instancje klasy wewnętrznej, zrobiłbyś:
public class Outer{ int nofInner; //this will count the inner class //instances of this (Outer)object //(you know, they "belong" to an object) static int totalNofInner; //this will count all //inner class instances of all Outer objects class Inner { public Inner(){ nofInner++; totalNofInner++; } } }
źródło
final
wtedy deklarowane ?W prostych słowach, niestatyczne klasy wewnętrzne są zmiennymi instancji dla klasy zewnętrznej i są tworzone tylko wtedy, gdy tworzona jest klasa zewnętrzna, a obiekt klasy zewnętrznej jest tworzony w czasie wykonywania, podczas gdy zmienne statyczne są tworzone w czasie ładowania klasy. Tak więc niestatyczna klasa wewnętrzna jest elementem środowiska uruchomieniowego, dlatego statyczna nie jest częścią niestatycznej klasy wewnętrznej.
UWAGA: traktuj klasy wewnętrzne zawsze jak zmienną dla klasy zewnętrznej, mogą one być statyczne lub niestatyczne, jak wszystkie inne zmienne.
źródło
static final
stałe.Ponieważ spowodowałoby to niejednoznaczność w znaczeniu „statyczności”.
Zaczerpnięte z „Core Java SE 9 for the Impatient” autorstwa Cay S. Horstmanna. Str. 90 Rozdział 2.6.3
źródło
Myślę, że to dla spójności. Chociaż wydaje się, że nie ma dla niego żadnych ograniczeń technicznych, nie byłbyś w stanie uzyskać dostępu do statycznych elementów klasy wewnętrznej z zewnątrz, tj.
OuterClass.InnerClass.i
Ponieważ środkowy krok nie jest statyczny.źródło
static final
stałe.