Я просматривал код Java LinkedList
и заметил, что он использует статический вложенный класс Entry
.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
В чем причина использования статического вложенного класса, а не нормального внутреннего класса?
Единственная причина, по которой я мог придумать, заключалась в том, что Entry не имеет доступа к переменным экземпляра, поэтому с точки зрения ООП он лучше инкапсулируется.
Но я подумал, что могут быть и другие причины, например, производительность. Что бы это могло быть?
Заметка. Я надеюсь, что мои термины верны, я бы назвал это статическим внутренним классом, но я думаю, что это неправильно: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
Ответы:
На странице Sun, на которую вы ссылаетесь, есть несколько ключевых отличий:
Там нет необходимости ,
LinkedList.Entry
чтобы быть класс верхнего уровня , как это только используетсяLinkedList
(есть некоторые другие интерфейсы , которые также имеют статические вложенные классы с именамиEntry
, такими какMap.Entry
- то же понятие). А поскольку ему не нужен доступ к членам LinkedList, имеет смысл, чтобы он был статичным - это гораздо более чистый подход.Как отмечает Джон Скит , я думаю, что если вы используете вложенный класс, лучше начать с того, чтобы он был статическим, а затем решить, действительно ли он должен быть нестатичным, основываясь на вашем использовании.
источник
#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
как это возможно, если один абзац перед документами говорит: «Static nested classes do not have access to other members of the enclosing class
Может быть, они хотели бы сказать: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
и это свидетельствует еще одно интересное свойствоnon-static inner classes
, а такжеanonymous inner classes
илиlocal classes defined inside a block
: они не могут иметь вno-arg
конструктор причина в компилятор неявно предварять последовательность Arg каждого конструктора, чтобы передать ссылку на экземпляр объемлющего класс. Довольно простоНа мой взгляд, вопрос должен быть наоборот, когда вы видите внутренний класс - действительно ли он должен быть внутренним классом, с дополнительной сложностью и неявной (а не явной и более ясной, IMO) ссылкой на экземпляр вмещающего класса?
Имейте в виду, я предвзят как фанат C # - C # не имеет эквивалента внутренних классов, хотя у него есть вложенные типы. Я не могу сказать, что я пропустил внутренние классы еще :)
источник
Здесь есть неочевидные проблемы с хранением памяти, которые необходимо учитывать. Так как нестатический внутренний класс поддерживает неявную ссылку на свой «внешний» класс, если на экземпляр внутреннего класса жестко ссылаются, то на внешний экземпляр также жестко ссылаются. Это может привести к некоторым царапинам, когда внешний класс не является сборщиком мусора, даже если кажется, что ничто на него не ссылается.
источник
Ну, во-первых, нестатические внутренние классы имеют дополнительное скрытое поле, которое указывает на экземпляр внешнего класса. Поэтому, если бы класс Entry не был статичным, то, помимо доступа, в котором он не нуждается, он будет содержать около четырех указателей вместо трех.
Как правило, я бы сказал, что если вы определяете класс, который в основном должен действовать как набор элементов данных, например, как "struct" в C, подумайте о том, чтобы сделать его статичным.
источник
Статический внутренний класс используется в шаблоне компоновщика. Статический внутренний класс может создавать экземпляр своего внешнего класса, который имеет только закрытый конструктор. Таким образом, вы можете использовать статический внутренний класс для создания экземпляра внешнего класса, который имеет только закрытый конструктор. Вы не можете сделать то же самое с внутренним классом, так как вам нужно создать объект внешнего класса до доступа к внутреннему классу.
Это выведет x: 1
источник
Статический вложенный класс, как и любой другой внешний класс, не имеет доступа к членам внешнего класса.
Просто для удобства упаковки мы можем объединить статические вложенные классы в один внешний класс для удобства чтения. Кроме этого нет другого варианта использования статического вложенного класса.
Пример такого использования вы можете найти в файле Android R.java (resources). Папка Res Android содержит макеты (содержащие рисунки экрана), папку для рисования (содержащую изображения, используемые для проекта), папку значений (которая содержит строковые константы) и т. Д.
Так как все папки являются частью папки Res, android tool генерирует файл R.java (resources), который внутренне содержит множество статических вложенных классов для каждой из своих внутренних папок.
Вот как выглядит файл R.java, созданный в Android: здесь они используются только для удобства упаковки.
источник
С http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :
источник
Простой пример:
Если не статический класс, экземпляр не может быть создан, кроме как в экземпляре высшего класса (не в примере, где main является статической функцией)
источник
Одна из причин статического и нормального состояния связана с загрузкой классов. Вы не можете создать экземпляр внутреннего класса в конструкторе его родителя.
PS: я всегда понимал, что «вложенные» и «внутренние» взаимозаменяемы. В терминах могут быть тонкие нюансы, но большинство разработчиков Java поймут это.
источник
Нестатические внутренние классы могут привести к утечкам памяти, в то время как статический внутренний класс защитит от них. Если внешний класс содержит значительные данные, это может снизить производительность приложения.
источник
Я не знаю о разнице в производительности, но, как вы говорите, статический вложенный класс не является частью экземпляра включающего класса. Кажется, проще создать статический вложенный класс, если вам действительно не нужно, чтобы он был внутренним классом.
Это немного похоже на то, почему я всегда делаю свои переменные окончательными в Java - если они не окончательные, я знаю, что с ними происходит что-то смешное. Если вы используете внутренний класс вместо статического вложенного класса, должна быть веская причина.
источник
Использование статического вложенного класса вместо нестатического может в некоторых случаях сэкономить место. Например: реализация
Comparator
внутри класса, скажем, Student.Затем он
static
гарантирует, что в классе Student есть только один Comparator, а не создает новый экземпляр каждый раз, когда создается новый экземпляр Student.источник
Преимущество внутреннего класса--
Без существующего внешнего класса внутренний класс не будет существовать.
Есть четыре типа внутреннего класса.
точка ---
чтобы вызвать нормальный внутренний класс в статической области внешнего класса.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
inorder для вызова нормального внутреннего класса в области экземпляра внешнего класса.
Inner i=new Inner();
Чтобы вызвать нормальный внутренний класс снаружи внешнего класса.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
Внутренний класс Это указатель на внутренний класс.
this.member-current inner class outerclassname.this--outer class
для внутреннего класса применим модификатор - public, default,
final,abstract,strictfp,+private,protected,static
external $ inner - это имя внутреннего класса.
внутренний класс внутри метода экземпляра, тогда мы можем получить доступ к статическому и экземпляру поля внешнего класса.
Класс 10.inner внутри статического метода, тогда мы можем получить доступ только к статическому полю
внешний класс.
источник