Внутренний класс Java и статический вложенный класс

в чем основное различие между внутренним классом и статическим вложенным классом в Java? Играет ли дизайн / реализация роль в выборе одного из них?

24 ответов


С Java Учебник:

вложенные классы делятся на две категории: статические и нестатические. Вложенные классы, объявленные статическими, просто называются статическими вложенными классами. Нестатические вложенные классы называются внутренними классами.

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

OuterClass.StaticNestedClass

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

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

объекты, являющиеся экземплярами внутреннего класса, существуют в экземпляре внешнего класса. Рассмотрим следующие классы:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

экземпляр InnerClass может существовать только в экземпляре OuterClass и имеет прямой доступ к методам и полям его заключающего экземпляра.

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

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

посмотреть: Java Tutorial-Вложенные Классы

для полноты обратите внимание, что существует также такая вещь, как внутренний класс без экземпляр включения:

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

здесь new A() { ... } это внутренний класс, определенный в статическом контексте и не имеет заключительного экземпляра.


на учебник Java говорит:

терминология: вложенные классы разделить на две категории: статические и не статичен. Вложенные классы, которые объявлены static просто называются статические вложенные классы. Нестатический вложенные классы называются внутренними занятия.

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

классы могут быть вложенными ad infinitum, например, класс A может содержать класс B, который содержит класс C, который содержит класс D и т. д. Однако более одного уровня гнездования классов встречается редко, так как это, как правило, плохой дизайн.

существует три причины, по которым вы можете создать вложенный класс:

  • организация: иногда кажется наиболее разумным сортировать класс в пространство имен другого класса, особенно когда он не будет использоваться в любой другой контекст
  • access: вложенные классы имеют специальный доступ к переменным / полям их содержащих классов (точно, какие переменные/поля зависят от типа вложенного класса, будь то внутренний или статический).
  • удобство: необходимость создания нового файла для каждого нового типа беспокоит, опять же, особенно когда тип будет использоваться только в одном контексте

здесь четыре вида вложенного класса в Java. Короче говоря, они являются:

  • статический класс: объявлен статическим членом другого класса
  • внутренний класс: объявлена как член экземпляра другого класса
  • локальный внутренний класс: объявленные внутри метода экземпляра другого класса
  • анонимный внутренний класс: как локальный внутренний класс, но написан как выражение, которое возвращает один объект

позвольте мне подробнее.


Статические Классы

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

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

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

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


Внутренние Классы

внутренний класс-это класс объявленный как нестатический член другого класса:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

как и со статическим классом, внутренний класс известен как квалифицированный по его имени содержащего класса,пицца.Носорог.Козел, но внутри содержащего класса он может быть известен по его простому имени. Однако, каждый экземпляр внутреннего класса привязан к конкретному экземпляру его содержащий класс: выше,Коза создано в Джерри, неявно привязан к носорог экземпляр этой на Джерри. В противном случае, мы связаны носорог экземпляр явный, когда мы создаем экземпляр Коза:

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

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

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

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

во внутреннем классе вы можете обратиться к этой содержащего класса as носорог.это, а вы можете использовать этой для обозначения его членов,например, носорог.этот.Барри!--18-->.


Локальные Внутренние Классы

локальный внутренний класс-это класс, объявленный в теле метода. Такой класс известен только в его пределах содержащий метод, поэтому он может быть только создан и иметь доступ к его элементам в своем содержащем методе. Выигрыш заключается в том, что локальный экземпляр внутреннего класса привязан и может получить доступ к конечным локальным переменным его содержащего метода. Когда экземпляр использует конечный локальный содержащего его метода, переменная сохраняет значение, которое она имела во время создания экземпляра, даже если переменная вышла из области видимости (это фактически грубая, ограниченная версия Java закрытия.)

поскольку локальный внутренний класс не является членом класса или пакета, он не объявляется с уровнем доступа. (Было ясно, однако, что его собственные члены имеют уровни доступа, как в обычном классе.)

если локальный внутренний класс объявлен в методе экземпляра, экземпляр внутреннего класса привязывается к экземпляру, удерживаемому содержащим методом этой во время создания экземпляра и экземпляра содержащего класса члены доступны, как во внутреннем классе экземпляра. Локальный внутренний класс создается просто via его имя, например локальный внутренний класс кошки экземпляров новый кот(), не новое это.Cat() как и следовало ожидать.


Анонимные Внутренние Классы

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

new *ParentClassName*(*constructorArgs*) {*members*}

это выражение, возвращающее новый экземпляр неназванного класса, который удлиняет ParentClassName. Вы не можете предоставить свой собственный конструктор; скорее, один неявно предоставляется, который просто вызывает супер конструктор, поэтому предоставленные аргументы должны соответствовать супер конструктору. (Если родитель содержит несколько конструкторов, называется "самый простой", "самый простой", как определено довольно сложным набором правил, не стоит беспокоиться, чтобы узнать подробно-просто обратите внимание на то, что NetBeans или Eclipse говорят вам.)

кроме того, вы можете указать интерфейс для реализации:

new *InterfaceName*() {*members*}

такое объявление создает новый экземпляр неназванного класса, который расширяет объект и реализует InterfaceName. Опять же, вы не можете предоставить свой собственный конструктор; в этом случае Java неявно предоставляет конструктор no-arg, do-nothing (поэтому в этом случае никогда не будет аргументов конструктора).

даже если вы не можете дать анонимный конструктор внутреннего класса, вы все равно можете выполнить любую настройку, используя блок инициализатора (блок {}, расположенный вне любого метода).

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


Я не думаю, что реальная разница стала ясной в приведенных выше ответах.

во-первых, чтобы получить правильные условия:

  • вложенный класс-это класс, который содержится в другом классе на уровне исходного кода.
  • он статичен, если вы объявите его с статический модификатор.
  • нестатический вложенный класс называется внутренним классом. (Я остаюсь с нестатическим вложенным классом.)

ответ Мартина прав, поэтому далеко. Однако фактический вопрос: какова цель объявления вложенного класса статическим или нет?

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

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

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

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

более хардкорные объяснения следующие:

если вы посмотрите на байт-коды Java, которые компилятор генерирует для (нестатического) вложенного класса, это может стать еще более ясным:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

как вы можете видеть, компилятор создает скрытое поле Container this. Это задается в конструкторе, который имеет дополнительный параметр типа Container для указания заключающего экземпляра. Вы не можете видеть этот параметр в источнике, но компилятор неявно создает для вложенный класс.

Мартин
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

было бы так скомпилировано для вызова чего-то вроде (в байт-кодах)

new InnerClass(outerObject)

для полноты картины:

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


Я думаю, что ни один из приведенных выше ответов не объясняет вам реальную разницу между вложенным классом и статическим вложенным классом с точки зрения дизайна приложения:

обзор

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

разница

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

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

вывод

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


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

вложенные классы-это классы, определенные внутри тела другого заключающего класса. Они бывают двух типов - статические и нестатические.

они относятся как к членам включающего класса, поэтому вы можете указать любой из четырех спецификаторов доступа - private, package, protected, public. У нас нет этой роскоши с классами верхнего уровня, которые могут быть объявлены только public или пакет-частный.

внутренние классы aka не-стековые классы имеют доступ к другим членам верхнего класса, даже если они объявлены частными, а статические вложенные классы не имеют доступа к другим членам верхнего класса.

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

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

когда бы вы использовали внутренний класс?

подумайте о ситуации, когда Class A и Class B связаны Class B должен получить доступ к Class A членов, и Class B это относится только к Class A. На сцену выходят внутренние классы.

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

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

или

OuterClass.Inner2 inner = new OuterClass().new Inner2();

когда бы вы использовали статический внутренний класс?

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

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

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

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


Я думаю, что конвенция, которая обычно соблюдается, такова:

  • статический класс в классе верхнего уровня является вложенный класс
  • нестатический класс в классе верхнего уровня является внутренний класс, который в дальнейшем имеет еще две формы:
    • локальный класс - именованные классы, объявленные внутри блока как метод или конструктор тела
    • анонимный класс!--9--> - неназванные классы, экземпляры которых создаются в выражениях и операторах
, несколько очков помнит являются:
  • классы верхнего уровня и статический вложенный класс семантически одинаковы, за исключением того, что в случае статического вложенного класса он может делать статическую ссылку на частные статические поля/методы своего внешнего [родительского] класса и наоборот.

  • внутренние классы имеют доступ к переменным экземпляра заключающего экземпляра внешнего [родительского] класса. Однако не все внутренние классы имеют заключающие экземпляры, например внутренние классы в статических контекстах, например анонимный класс, используемый в статическом блоке инициализатора, не имеют.

  • анонимный класс по умолчанию расширяет родительский класс или реализует Родительский интерфейс, и нет никакого дополнительного предложения для расширения любого другого класса или реализации любых других интерфейсов. Итак,

    • new YourClass(){}; означает class [Anonymous] extends YourClass {}
    • new YourInterface(){}; означает class [Anonymous] implements YourInterface {}

Я считаю, что главный вопрос, который остается открытым, какой из них использовать и когда? Ну, это в основном зависит от того, с каким сценарием вы имеете дело, но чтение ответа, данного @jrudolph, может помочь вам принять какое-то решение.


вот ключевые различия и сходства между внутренним классом Java и статическим вложенным классом.

надеюсь, что это помогает!

внутренний класс

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

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • не может определить статические члены

  • не может есть класс или интерфейс декларация

статический вложенный класс

  • не удается получить доступ к внешний класс экземпляр методы или поля

  • не связан ни с одним экземпляром заключительного класса Итак, чтобы создать его:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

сходство

  • и внутренние классы может получить доступ даже Private поля и методы of внешний класс
  • и внешний класс иметь доступ к Private поля и методы of внутренние классы
  • оба класса могут иметь частный, защищенный или открытый доступ модификатор

Зачем Использовать Вложенные Классы?

согласно документации Oracle существует несколько причин (полная документация):

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

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

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


вложенный класс внутри класс

типа:

  1. статический вложенный класс
  2. нестатический вложенный класс [внутренний класс]

отличия:

нестатический вложенный класс [внутренний класс]

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

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

статический вложенный класс

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

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

Если вы хотите получить доступ к x, то напишите следующий внутренний метод

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

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

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

статические вложенные классы не связаны с внешним объектом, они быстрее, и они не принимают память кучи/стека, потому что ее нет необходимости создавать экземпляр такого класса. Поэтому эмпирическое правило состоит в том, чтобы попытаться определить статический вложенный класс с максимально ограниченной областью (private >= class >= protected >= public), а затем преобразовать его в внутренний класс (путем удаления" статического " идентификатора) и ослабьте область, если это действительно необходимо.


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

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

рассмотреть этот пример:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

хотя 'вложенные' и 'innerItem' оба объявлены как статические заключительные'. установка вложенных.innerItem не происходит до тех пор, пока класс не будет создан (или, по крайней мере, только после того, как вложенный статический элемент будет впервые указан), как вы можете убедиться сами в комментариях и раскомментировав строки, о которых я говорил выше. То же не держит верно для "outerItem".

по крайней мере это то, что я вижу в Java 6.0.


в случае создания экземпляра экземпляр non статический внутренний класс создается со ссылкой на объект внешнего класса, в котором он определен. Этот значит, есть экземпляр заключением. Но экземпляр статического внутреннего класса создается со ссылкой на внешний класс, а не с ссылка на объект внешнего класса. Это значит это не включайте экземпляр.

например:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}

Я не думаю, что здесь есть что добавить, большинство ответов прекрасно объясняют различия между статическим вложенным классом и внутренними классами. Однако рассмотрите следующую проблему при использовании вложенных классов против внутренних классов. Как упоминается в нескольких ответах, внутренние классы не могут быть созданы без и экземпляра их заключительного класса, что означает, что они провести a указатель к экземпляру их заключая класса который может привести к переполнению памяти или исключение переполнения стека из-за того, что GC не сможет собирать мусор, даже если они больше не используются. Чтобы сделать это ясно, проверьте следующий код:

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

Если вы удалите комментарий // inner = null; программа выйдет "Я буду уничтожен !", но держать это прокомментировано не будет.
Причина в том, что Белый внутренний экземпляр по-прежнему ссылается на GC, не может его собрать и потому что он ссылается (имеет указатель на) внешний экземпляр тоже не собирается. Имея достаточно этих объектов в вашем проекте и может закончиться память.
По сравнению со статическими внутренними классами, которые не содержат точки для экземпляра внутреннего класса, потому что он не связан с экземпляром, а связан с классом. Вышеуказанная программа может печатать "Я буду уничтожен ! " если вы делаете внутренний класс статическим и создаете экземпляр с Outer.Inner i = new Outer.Inner();


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

public class Outer {
    public class Inner {}

    public static class Nested {}
}

это не очень широко принятое определение, хотя.


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


Эммм... внутренний класс-это вложенный класс... вы имеете в виду анонимный класс и внутренний класс?

Edit: если вы действительно имели в виду внутренний vs анонимный... внутренний класс-это просто класс, определенный в классе, таком как:

public class A {
    public class B {
    }
}

в то время как анонимный класс является расширением класса, определенного анонимно, поэтому фактический " класс не определен, как в:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Далее Редактировать:

Википедия утверждает, что есть разница на Java, но Я работаю с Java в течение 8 лет, и это первый раз, когда я услышал такое различие... не говоря уже о том, что там нет ссылок для резервного копирования претензии... суть в том, что внутренний класс-это класс, определенный внутри класса (статический или нет), а вложенный-это просто еще один термин, означающий то же самое.

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


таргетинг учащегося, который новичок в Java и / или вложенных классов

вложенные классы могут быть либо:
1. Статические вложенные классы.
2. Нестатические вложенные классы. (также известный как внутренние классы) =>пожалуйста, помните это


1.Внутренние классы
Пример:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


внутренние классы являются подмножествами вложенных классы:

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

специальность внутреннего класса:

  • экземпляр внутреннего класса имеет доступ ко всем из члены внешнего класса, даже те, которые отмечены как "частные"


2.Статические Вложенные Классы:
Пример:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Случай 1: создание экземпляра статического вложенного класса из не заключающего класса

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

случай 2: создание экземпляра статического вложенного класса из заключительного класса

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

специальность статических классов:

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

вывод:
вопрос: в чем основное различие между внутренним классом и статическим вложенным классом в Java?
ответ: просто пройдите специфику каждого класса, упомянутого выше.


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

что такое внутренний класс в Java?

любой класс, который не является верхним уровнем или объявлен внутри другого класса, известен как вложенный класс и из этих вложенных классов класс, который объявлен нестатическим, известен как внутренний класс в Java. в Java есть три вида внутреннего класса:

1) локальный внутренний класс объявлен внутри блока кода или метод.
2) анонимный внутренний класс-это класс, который не имеет имени для ссылки и инициализации в том же месте, где он создается.
3) внутренний класс члена-объявляется как нестатический член внешнего класс.

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}

что такое вложенный статический класс в Java?

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

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

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}

Ref:внутренний класс и вложенный статический класс в Java с примерами


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

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

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


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

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

когда мы объявить нестатический член класса внутри класса он известен как внутренний класс. Внутренний класс можно продемонстрировать следующим образом:

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}

ниже приведен пример static nested class и inner class:

OuterClass.java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}

разница в том, что вложенное объявление класса, которое также является статическим, может быть создано вне заключающего класса.

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

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


прежде всего, нет такого класса, называемого статическим классом.Статический модификатор, используемый с внутренним классом (называемым вложенным классом), говорит, что он является статическим членом внешнего класса, что означает, что мы можем получить к нему доступ как с другими статическими членами, так и без какого-либо экземпляра внешнего класса. (Что является преимуществом static изначально.)

разница между использованием вложенного класса и обычного внутреннего класса:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

Сначала мы можем создать экземпляр Outerclass, затем мы можем получить доступ Внутренний.

но если класс вложен, то синтаксис:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

который использует статический синтаксис как обычную реализацию статического ключевого слова.


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

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }

просто некоторые надстройки после того, как вы прочитали Java-учебник oracle в классах и объектах. Это может помочь, если вы знаете модель памяти Java для внутреннего класса и статического вложенного класса. Пожалуйста, прочитайте следующие три вопроса, чтобы получить философию того, почему внутренний класс и статический вложенный класс разработаны Java таким образом. И тогда вы можете знать, когда использовать внутренний класс и когда использовать статический вложенный класс.

как объект внутреннего класса находится в память?

управление памятью-внутренний статический класс в Java

когда статический вложенный класс (и статические члены в нем) загружается в память?

затем прочитать это, чтобы сравнить внутренний класс и статический вложенный класс.

в чем преимущество создания внутреннего класса как статического с Java?