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

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

public class LinkedList<E> ... {
...

 private static class Entry<E> { ... }

}

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

Помните, я предвзято настроен как поклонник С# - у С# нет эквивалента внутренних классов, хотя у него есть вложенные типы. Я не могу сказать, что я пропустил внутренние занятия:)

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Вот внешний вид файла 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;
    }
}

Ответ 6

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

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

Ответ 7

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

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();
}
}

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

Ответ 11

В соответствии с сайтом Oracle ниже приведены основные преимущества использования вложенного класса (статические или нестатические): http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Зачем использовать вложенные классы?

Принудительные причины использования вложенных классов включают следующее:

Это способ логически группировать классы, которые используются только в одном   place: Если класс полезен только для одного другого класса, тогда он   логически встроить его в этот класс и сохранить вместе. гнездование   такие "вспомогательные классы" делают их пакет более упорядоченным.

Это увеличивает инкапсуляцию: рассмотрим два класса верхнего уровня, A и B,
  где B нуждается в доступе к членам A, которые в противном случае были бы   объявлено частным. Скрывая класс B в классе A, члены A   могут быть объявлены частными, а B - доступ к ним. Кроме того, B   сам может быть скрыт от внешнего мира.

Это может привести к более легко читаемому и поддерживаемому коду: вложение небольших классов внутри   классы верхнего уровня помещают код ближе к тому, где он используется.

Ответ 12

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

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

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

Ответ 13

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

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

Ответ 14

Преимущество внутреннего класса -

  • одноразовое использование
  • поддерживает и улучшает инкапсуляцию.
  • готовность
  • доступ к закрытому полю

Без существующего внутреннего класса внешнего класса не будет существовать.

class car{
    class wheel{

    }
}

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

  • нормальный внутренний класс
  • Метод Локальный Внутренний класс
  • Анонимный внутренний класс
  • статический внутренний класс

точка ---

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

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

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

    Inner i=new Inner();

  • inorder для вызова нормального внутреннего класса вне внешнего класса.

    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 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
            }
        }
    }
}