Szukałem na kod Java dla LinkedList
i zauważył, że wszystko jest używać statycznego zagnieżdżonych klasy Entry
.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
Jaki jest powód używania statycznej klasy zagnieżdżonej zamiast normalnej klasy wewnętrznej?
Jedynym powodem, o którym mogłem pomyśleć, było to, że Entry nie ma dostępu do zmiennych instancji, więc z punktu widzenia OOP ma lepszą enkapsulację.
Ale pomyślałem, że mogą być inne powody, może wydajność. Co to może być
Uwaga. Mam nadzieję, że moje warunki są prawidłowe, nazwałbym to statyczną klasą wewnętrzną, ale myślę, że to źle: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
Odpowiedzi:
Strona Sun, do której prowadzi link, ma kilka kluczowych różnic między nimi:
Nie ma potrzeby,
LinkedList.Entry
aby istniała klasa najwyższego poziomu, ponieważ jest ona używana tylko przezLinkedList
(istnieją inne interfejsy, które mają również nazwane statyczne klasy zagnieżdżoneEntry
, takie jakMap.Entry
- ta sama koncepcja). A ponieważ nie potrzebuje on dostępu do członków LinkedList, ma sens, aby był statyczny - jest to znacznie czystsze podejście.Jak zauważa Jon Skeet , myślę, że lepszym pomysłem jest, jeśli używasz zagnieżdżonej klasy, aby zacząć od statyczności, a następnie zdecydować, czy naprawdę musi ona być niestatyczna na podstawie twojego użycia.
źródło
#comment113712_253507
A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class
jak to możliwe, jeśli tylko akapit przed dokumentami mówi:Static nested classes do not have access to other members of the enclosing class
Może chcieliby powiedzieć:A nested (non-static) class interacts with the instance members of its outer class (and other classes) just like any other top-level class
An inner class interacts with the instance members through an implicit reference to its enclosing class
, a ten zwraca uwagę, innym interesującym mienianon-static inner classes
jak równieżanonymous inner classes
czylocal classes defined inside a block
: wszystkie one nie mogą mieć dono-arg
konstruktora spowodować kompilator niejawnie poprzedzić sekwencję arg każdego konstruktora, aby przekazać referencję instancji załączania klasa. Dość proste.Moim zdaniem pytanie powinno być odwrotne, ilekroć zobaczysz klasę wewnętrzną - czy naprawdę musi to być klasa wewnętrzna, z dodatkową złożonością i niejawnym (a nie wyraźnym i wyraźniejszym odniesieniem do IMO) do instancji klasy zawierającej?
Pamiętaj, że jestem stronniczy jako fan C # - C # nie ma odpowiednika klas wewnętrznych, chociaż ma zagnieżdżone typy. Nie mogę powiedzieć, że opuściłem jeszcze klasy wewnętrzne :)
źródło
Należy wziąć pod uwagę nieoczywiste problemy z pamięcią. Ponieważ niestatyczna klasa wewnętrzna utrzymuje niejawne odniesienie do swojej klasy „zewnętrznej”, jeśli instancja klasy wewnętrznej jest silnie przywołana, to również instancja zewnętrzna jest silnie przywołana. Może to prowadzić do porysowania głowy, gdy klasa zewnętrzna nie jest gromadzona, nawet jeśli wydaje się, że nic do niej nie odwołuje się.
źródło
Po pierwsze, niestatyczne statyczne klasy wewnętrzne mają dodatkowe, ukryte pole, które wskazuje na instancję klasy zewnętrznej. Więc jeśli klasa Entry nie byłaby statyczna, to oprócz tego, że nie potrzebuje dostępu, nosiłaby cztery wskaźniki zamiast trzech.
Zasadniczo powiedziałbym, że jeśli zdefiniujesz klasę, która zasadniczo działa jako zbiór elementów danych, takich jak „struct” w C, rozważ ustawienie statyczne.
źródło
Statyczna klasa wewnętrzna jest używana we wzorcu konstruktora. Statyczna klasa wewnętrzna może tworzyć instancję swojej klasy zewnętrznej, która ma tylko prywatnego konstruktora. Możesz więc użyć statycznej klasy wewnętrznej do utworzenia klasy zewnętrznej, która ma tylko prywatnego konstruktora. Nie możesz zrobić tego samego z klasą wewnętrzną, ponieważ musisz mieć obiekt klasy zewnętrznej utworzony przed uzyskaniem dostępu do klasy wewnętrznej.
To wyświetli x: 1
źródło
statyczna klasa zagnieżdżona jest jak każda inna klasa zewnętrzna, ponieważ nie ma dostępu do elementów klasy zewnętrznej.
Tylko dla wygody pakowania możemy pogrupować statycznie zagnieżdżone klasy w jedną klasę zewnętrzną w celu zapewnienia czytelności. Poza tym nie ma innego przypadku użycia statycznej klasy zagnieżdżonej.
Przykład takiego zastosowania można znaleźć w pliku Android R.java (zasoby). Folder Res Androida zawiera układy (zawierające projekty ekranów), folder do rysowania (zawierający obrazy użyte w projekcie), folder wartości (który zawiera stałe ciągów) itp.
Ponieważ wszystkie foldery są częścią folderu Res, narzędzie Android generuje plik R.java (zasoby), który wewnętrznie zawiera wiele statycznie zagnieżdżonych klas dla każdego z ich wewnętrznych folderów.
Oto wygląd pliku R.java wygenerowanego w Androidzie: tutaj używają tylko dla wygody pakowania.
źródło
From http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :
źródło
Prosty przykład:
Jeśli nie jest statyczny, nie można utworzyć instancji klasy z wyjątkiem instancji wyższej klasy (więc nie w przykładzie, w którym main jest funkcją statyczną)
źródło
Jednym z powodów statycznego vs. normalnego jest ładowanie klas. Nie można utworzyć instancji klasy wewnętrznej w konstruktorze jej rodzica.
PS: Zawsze rozumiałem „zagnieżdżone” i „wewnętrzne” jako wymienne. Mogą występować subtelne niuanse, ale większość programistów Java też to zrozumie.
źródło
Niestatyczne klasy wewnętrzne mogą powodować wycieki pamięci, podczas gdy statyczne klasy wewnętrzne będą przed nimi chronić. Jeśli klasa zewnętrzna przechowuje znaczne dane, może obniżyć wydajność aplikacji.
źródło
Nie wiem o różnicy w wydajności, ale jak mówisz, statyczna klasa zagnieżdżona nie jest częścią instancji klasy zamykającej. Wydaje się po prostu łatwiej stworzyć statyczną klasę zagnieżdżoną, chyba że naprawdę potrzebujesz, aby była to klasa wewnętrzna.
To trochę tak, dlaczego zawsze zmieniam moje zmienne na Javę - jeśli nie są ostateczne, wiem, że dzieje się z nimi coś śmiesznego. Jeśli używasz klasy wewnętrznej zamiast statycznej klasy zagnieżdżonej, powinien istnieć dobry powód.
źródło
Użycie statycznej klasy zagnieżdżonej zamiast niestatycznej może w niektórych przypadkach zaoszczędzić miejsce. Na przykład: zaimplementowanie
Comparator
klasy wewnątrz, powiedz Student.Następnie
static
zapewnia, że klasa ucznia ma tylko jeden komparator, zamiast tworzyć nową za każdym razem, gdy tworzona jest nowa instancja ucznia.źródło
Zaleta klasy wewnętrznej
Bez istnienia klasy zewnętrznej klasa wewnętrzna nie istniałaby.
Istnieją cztery rodzaje klas wewnętrznych.
punkt ---
w celu wywołania normalnej klasy wewnętrznej w statycznym obszarze klasy zewnętrznej.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
w celu wywołania normalnej klasy wewnętrznej w instancji obszaru klasy zewnętrznej.
Inner i=new Inner();
w celu wywołania normalnej klasy wewnętrznej poza klasą zewnętrzną.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
inside Klasa wewnętrzna Ten wskaźnik do klasy wewnętrznej.
this.member-current inner class outerclassname.this--outer class
dla klasy wewnętrznej obowiązującym modyfikatorem jest - public, default,
final,abstract,strictfp,+private,protected,static
outer $ inner to nazwa klasy wewnętrznej.
metodę klasy wewnętrznej wewnątrz instancji, wtedy możemy uzyskać dostęp do pola statycznego i instancji klasy zewnętrznej.
10. wewnętrzna klasa wewnątrz metody statycznej, wtedy możemy uzyskać dostęp tylko do pola statycznego
klasa zewnętrzna.
źródło