Статический вложенный class в Java, почему?

Я смотрел Java-код для LinkedList и заметил, что он использовал статический вложенный class Entry .

 public class LinkedList ... { ... private static class Entry { ... } } 

В чем причина использования статического вложенного classа, а не обычного внутреннего classа?

Единственная причина, по которой я мог думать, заключалась в том, что Entry не имеет доступа к переменным экземпляра, поэтому с точки зрения ООП она имеет лучшую инкапсуляцию.

Но я думал, что могут быть другие причины, возможно, производительность. Что это может быть?

Заметка. Надеюсь, что мои термины верны, я бы назвал это статическим внутренним classом, но я думаю, что это неправильно: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

    На странице Sun, с которой вы ссылаетесь, есть некоторые ключевые различия между ними:

    Вложенный class является членом его охватывающего classа. Нестатические вложенные classы (внутренние classы) имеют доступ к другим членам охватывающего classа, даже если они объявлены частными. Статические вложенные classы не имеют доступа к другим членам входящего classа.

    Примечание. Статический вложенный class взаимодействует с членами экземпляра его внешнего classа (и других classов), как и любой другой class верхнего уровня. По сути, статический вложенный class поведенчески является classом верхнего уровня, который был вложен в другой class верхнего уровня для удобства упаковки.

    Нет необходимости LinkedList.Entry с classом верхнего уровня, поскольку он используется только LinkedList (есть и другие интерфейсы, которые также имеют статические вложенные classы с именем Entry , такие как Map.Entry – та же концепция). И поскольку ему не нужен доступ к членам LinkedList, для него имеет смысл быть статичным – это гораздо более чистый подход.

    Как указывает Джон Скит , я думаю, что лучше понять, используете ли вы вложенный class, чтобы начать с того, что он является статичным, а затем решить, действительно ли он должен быть нестационарным на основе вашего использования.

    На мой взгляд, вопрос должен быть наоборот, когда вы видите внутренний class – действительно ли это должен быть внутренний class, с дополнительной сложностью и неявной (а не явной и ясной, IMO) ссылкой на экземпляр classа?

    Имейте в виду, я предвзятый как поклонник C # – у C # нет эквивалента внутренних classов, хотя у него есть вложенные типы. Я не могу сказать, что я пропустил внутренние занятия еще 🙂

    Здесь необходимо учитывать неявные проблемы с сохранением памяти. Так как нестатический внутренний class поддерживает неявную ссылку на его «внешний» class, если экземпляр внутреннего classа сильно привязан, то внешний экземпляр также сильно ссылается. Это может привести к некоторому царапинам головы, когда внешний class не собирает мусор, хотя кажется, что ничего не ссылается на него.

    Во-первых, нестатические внутренние classы имеют дополнительное скрытое поле, указывающее на экземпляр внешнего classа. Поэтому, если class Entry не был статичным, то, помимо доступа, который ему не нужен, он будет иметь четыре указателя вместо трех.

    Как правило, я бы сказал, если вы определите class, который в принципе должен действовать как набор элементов данных, например «структура» на C, подумайте о том, чтобы сделать его статическим.

    статический вложенный class подобен любому другому внешнему classу, поскольку он не имеет доступа к внешним членам classа.

    Для удобства упаковки мы можем вводить статические вложенные classы в один внешний class для удобства чтения. Помимо этого нет другого случая использования статического вложенного classа.

    Пример такого использования можно найти в файле Android R.java (resources). В папке «Res» android содержатся макеты (содержащие экраны), выпадающая папка (содержащая изображения, используемые для проекта), папка значений (которая содержит строковые константы) и т. Д.

    Sine все папки являются частью папки Res, а инструмент android создает файл R.java (resources), который внутри содержит множество статических вложенных classов для каждой из своих внутренних папок.

    Вот внешний вид файла R.java, созданного в android: здесь они используются только для удобства упаковки.

     /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.techpalle.b17_testthird; public final class R { public static final class drawable { public static final int ic_launcher=0x7f020000; } public static final class layout { public static final int activity_main=0x7f030000; } public static final class menu { public static final int main=0x7f070000; } public static final class string { public static final int action_settings=0x7f050001; public static final int app_name=0x7f050000; public static final int hello_world=0x7f050002; } } 

    Статический внутренний class используется в шаблоне строителя. Статический внутренний class может создать экземпляр внешнего classа, который имеет только частный конструктор. Таким образом, вы можете использовать статический внутренний class для создания экземпляра внешнего classа, который имеет только частный конструктор. Вы не можете сделать то же самое с внутренним classом, поскольку вам нужен объект внешнего classа, созданный до доступа к внутреннему classу.

     class OuterClass { private OuterClass(int x) { System.out.println("x: " + x); } static class InnerClass { public static void test() { OuterClass outer = new OuterClass(1); } } } public class Test { public static void main(String[] args) { OuterClass.InnerClass.test(); // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside. } } 

    Это выведет x: 1

    Простой пример:

     package test; public class UpperClass { public static class StaticInnerClass {} public class InnerClass {} public static void main(String[] args) { // works StaticInnerClass stat = new StaticInnerClass(); // doesn't compile InnerClass inner = new InnerClass(); } } 

    Если нестатический class не может быть экземпляр исключен, например, в экземпляре верхнего classа (поэтому не в примере, где main является статической функцией)

    С http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :

    Используйте нестатический вложенный class (или внутренний class), если вам нужен доступ к непубличным полям и методам закрывающего экземпляра. Используйте статический вложенный class, если вы не требуете этого доступа.

    Одна из причин статического и нормального имеет отношение к загрузке classов. Вы не можете создать экземпляр внутреннего classа в конструкторе его родителя.

    PS: Я всегда понимал, что «вложенный» и «внутренний» должен быть взаимозаменяемым. В терминах могут быть тонкие нюансы, но большинство разработчиков Java поймут.

    Нестационарные внутренние classы могут привести к утечке памяти, в то время как статический внутренний class защитит их. Если внешний class содержит значимые данные, он может снизить производительность приложения.

    Использование статического вложенного classа, а не нестатического, в некоторых случаях может сэкономить места. Например: реализация Comparator внутри classа, скажем, студента.

     public class Student { public static final Comparator BY_NAME = new ByName(); private final String name; ... private static class ByName implements Comparator { public int compare() {...} } } 

    Затем static гарантирует, что class Student имеет только один компаратор, а не создает новый экземпляр каждый раз, когда создается новый экземпляр студента.

    Я не знаю о разнице в производительности, но, как вы говорите, статический вложенный class не является частью экземпляра охватывающего classа. Кажется, проще создать статический вложенный class, если вам действительно не нужен внутренний class.

    Это немного похоже на то, почему я всегда делаю свои переменные окончательными на Java – если они не окончательные, я знаю, что с ними что-то смешное. Если вы используете внутренний class вместо статического вложенного classа, должна быть веская причина.

    Преимущество внутреннего classа –

    1. одноразовое использование
    2. поддерживает и улучшает инкапсуляцию
    3. readibility
    4. частный доступ к полям

    Без существующего внешнего classа внутренний class не будет существовать.

     class car{ class wheel{ } } 

    Существует четыре типа внутреннего classа.

    1. нормальный внутренний class
    2. Метод Локальный Внутренний class
    3. Анонимный внутренний class
    4. статический внутренний class

    точка —

    1. из статического внутреннего classа мы можем получить доступ только к статическому члену внешнего classа.
    2. Внутри внутреннего classа мы cananot объявить статический член.
    3. inorder для вызова нормального внутреннего classа в статической области внешнего classа.

      Outer 0=new Outer(); Outer.Inner i= O.new Inner();

    4. inorder для вызова нормального внутреннего classа в области экземпляра внешнего classа.

      Inner i=new Inner();

    5. чтобы вызвать обычный внутренний class вне внешнего classа.

      Outer 0=new Outer(); Outer.Inner i= O.new Inner();

    6. in Inner class Этот указатель на внутренний class.

      this.member-current inner class outerclassname.this--outer class

    7. для встроенного модификатора classа – public, default,

      final,abstract,strictfp,+private,protected,static

    8. external $ inner – это имя внутреннего имени classа.

    9. внутреннего classа внутри экземпляра, тогда мы можем использовать статический и экземплярный class внешнего classа.

    10.inner внутри статического метода, тогда мы можем получить доступ только к статическому полю

    внешний class.

     class outer{ int x=10; static int y-20; public void m1() { int i=30; final j=40; class inner{ public void m2() { // have accees x,y and j } } } } 
    Давайте будем гением компьютера.