Внутрішній клас Java та статичний вкладений клас


1765

У чому головна відмінність внутрішнього класу від статичного вкладеного класу на Java? Чи грає дизайн / реалізація роль у виборі одного з них?


65
Відповідь Джошуа Блоха знаходиться в Ефективному читанні на Javaitem 22 : Favor static member classes over non static
Раймонд Шенон

4
Для запису - це пункт 24 у 3-му виданні цієї ж книги.
ZeroCool

Відповіді:


1696

З навчального посібника Java :

Вкладені класи поділяються на дві категорії: статичні та нестатичні. Вкладені класи, які оголошені статичними, просто називаються статичними вкладеними класами. Нестатичні вкладені класи називають внутрішніми класами.

До статичних вкладених класів можна отримати доступ, використовуючи назву класу, що додається:

OuterClass.StaticNestedClass

Наприклад, щоб створити об’єкт для статичного вкладеного класу, використовуйте цей синтаксис:

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

Об'єкти, що є екземплярами внутрішнього класу, існують в екземплярі зовнішнього класу. Розглянемо наступні класи:

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

Екземпляр InnerClass може існувати лише в екземплярі OuterClass і має прямий доступ до методів і полів його екземпляра, що додається.

Щоб створити внутрішній клас, потрібно спочатку інстанціювати зовнішній клас. Потім створіть внутрішній об’єкт у зовнішньому об'єкті за допомогою цього синтаксису:

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

див .: Підручник Java - Вкладені класи

Для повноти зауважте, що існує також таке поняття, як внутрішній клас без прикладного екземпляра :

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

Тут new A() { ... }є внутрішній клас, визначений у статичному контексті і не має примірника, що обгороджує.


130
Майте на увазі, що ви також можете імпортувати статичний вкладений клас безпосередньо, тобто ви можете це зробити (у верхній частині файлу): import OuterClass.StaticNestedClass; тоді посилайтеся на клас так само, як на OuterClass.
Каміло Діаз Репка

4
@Martin Чи є якась конкретна технічна назва для цієї ідіоми створення внутрішнього класу OuterClass.InnerClass innerObject = outerObject.new InnerClass();?
Geek

7
Отже, для чого використовується приватний статичний вкладений клас? Я думаю, що ми не можемо інстанціювати його з іншого боку, як OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass ();
RoboAlex

1
@Ilya Kogan: Я мав на увазі, що я знаю, що ми можемо отримати доступ до батьківських полів класу статичні чи нестатичні (якщо дочірній клас нестатичний клас), я кілька разів використав їх функції, але мені було цікаво, що це за модель пам'яті вони слідують? чи охоплює поняття ООП їх окрему концепцію? якщо не там, де вони справді вписуються в OOP. Мені здається, що клас друзів :)
Мубашар

4
@martin, я знаю, що я дуже запізнююсь до цієї теми, але: це ваша змінна, a, це статичне поле класу. Це не означає анонімний клас, створений 'new A () {int t () {повернення 2; }} 'є статичним більше, ніж якби я просто призначив будь-який інший об'єкт статичному полі, a, як у: клас B {статичний недійсний основний (рядок s) {Aa = new A ()}} (A & B в тому ж самому пакет) Це не робить A статичний клас. Фраза "статичний контекст" у посиланні, цитованому в потоці, до якого ви посилаєтесь, неймовірно розпливчаста. Насправді це було відзначено у багатьох коментарях у цій темі.
ГрантРобертсон

599

Підручник Java говорить :

Термінологія: Вкладені класи поділяються на дві категорії: статичні та нестатичні. Вкладені класи, які оголошені статичними, просто називаються статичними вкладеними класами. Нестатичні вкладені класи називають внутрішніми класами.

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

Класи можуть бути вкладені ad infinitum , наприклад, клас A може містити клас B, який містить клас C, який містить клас D тощо. Однак більш ніж один рівень вкладання класу рідко, оскільки це, як правило, погана конструкція.

Ви можете створити вкладений клас з трьох причин:

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

На Яві є чотири види вкладеного класу . Якщо коротко, це:

  • статичний клас : оголошений статичним членом іншого класу
  • внутрішній клас : оголошений як член екземпляра іншого класу
  • локальний внутрішній клас : оголошений всередині методу інстанції іншого класу
  • анонімний внутрішній клас : як локальний внутрішній клас, але записаний як вираз, який повертає одноразовий об'єкт

Дозвольте детальніше розказати.


Статичні класи

Статичні класи - це найпростіший вид для розуміння, оскільки вони не мають нічого спільного з екземплярами класу, що містить.

Статичний клас - це клас, оголошений статичним членом іншого класу. Як і інші статичні члени, такий клас насправді є просто вішальником, який використовує клас, що містить, як простір імен, наприклад, клас Коза, оголошений статичним членом класу Rhino в пакеті піци , відомий під назвою pizza.Rhino.Goat .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Відверто кажучи, статичні класи - це досить нікчемна особливість, оскільки класи вже розділені на простори імен за пакетами. Єдиною реальною можливою причиною створення статичного класу є те, що такий клас має доступ до приватних статичних членів класу, але я вважаю це досить кульгавим обґрунтуванням існування функції статичного класу.


Внутрішні класи

Внутрішній клас - це клас, оголошений нестатичним членом іншого класу:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

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

Як і у випадку зі статичним класом, внутрішній клас відомий як кваліфікований за своїм ім'ям, що містить клас pizza.Rhino.Goat , але всередині класу, що містить його, він може бути відомий за його простою назвою. Однак кожен екземпляр внутрішнього класу прив’язаний до певного екземпляра класу, що містить його: вище, Коза, створена в джеррі , неявно пов'язана з екземпляром Rhino, це в Джеррі . В іншому випадку ми робимо явний екземпляр Rhino явним, коли інстанціюємо Goat :

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

(Зверніть увагу, що ви називаєте внутрішній тип як просто Козел у новому дивному синтаксисі: Java виводить тип містить із частини носорога . І, так, новий rhino.Goat () мав би більше сенсу і для мене.)

То що, це нас отримує? Ну, внутрішній екземпляр класу має доступ до членів екземпляра, що містить екземпляр класу. Ці члени екземплярів, що додаються, посилаються на внутрішній клас за допомогою їх простих імен, а не через це ( це у внутрішньому класі посилається на екземпляр внутрішнього класу, а не на асоційований екземпляр класу):

public class Rhino {

    private String barry;

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

У внутрішньому класі ви можете називати цей клас, що містить, як Rhino.this , і ви можете використовувати це для позначення його членів, наприклад, Rhino.this.barry .


Місцеві внутрішні класи

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

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

Якщо локальний внутрішній клас оголошено методом екземпляра, інстанція внутрішнього класу прив'язується до екземпляра, який утримується методом, що містить цей, на момент створення екземпляра, і тому члени екземплярів класу, що містять клас, доступні, як у екземплярі внутрішній клас. Місцевий внутрішній клас створюється примірником просто через його ім'я, наприклад, місцевий внутрішній клас Cat інстанціюється як новий Cat () , а не новий this.Cat (), як ви могли очікувати.


Анонімні внутрішні класи

Анонімний внутрішній клас - синтаксично зручний спосіб написання місцевого внутрішнього класу. Найчастіше локальний внутрішній клас інстанціюється не більше одного разу щоразу, коли його метод містить. Тоді було б непогано, якби ми могли поєднати визначення місцевого внутрішнього класу та його єдину інстанціювання в одну зручну синтаксичну форму, і було б також непогано, якби нам не довелося придумати назву для класу (менша кількість непосидних імена, які містить ваш код, тим краще). Анонімний внутрішній клас дозволяє обидві речі:

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

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

Можна також вказати інтерфейс для реалізації:

new *InterfaceName*() {*members*}

Така декларація створює новий екземпляр неназваного класу, який розширює Object та реалізує InterfaceName . Знову ж таки, ви не можете поставити власний конструктор; у цьому випадку Java неявно постачає конструктор no-arg, нічого робити (тому в цьому випадку аргументів конструктора ніколи не буде).

Незважаючи на те, що ви не можете надати конструктору анонімний внутрішній клас, ви все одно можете виконати будь-яку установку, яку ви хочете, використовуючи блок ініціалізатора (блок {}, розміщений поза будь-яким методом).

Будьте зрозумілі, що анонімний внутрішній клас - це просто менш гнучкий спосіб створення локального внутрішнього класу одним екземпляром. Якщо ви хочете локальний внутрішній клас, який реалізує кілька інтерфейсів або реалізує інтерфейси, одночасно розширюючи якийсь клас, відмінний від Object, або який вказує власний конструктор, ви застрягли, створюючи звичайний локальний внутрішній клас.


39
Чудова історія, дякую. Однак є одна помилка. Ви можете отримати доступ до полів зовнішнього класу з внутрішнього класу екземпляра за допомогою Rhino.this.variableName.
Трилер

2
Хоча ви не можете надати власний конструктор для анонімних внутрішніх класів, ви можете використовувати подвійну ініціалізацію дужок. c2.com/cgi/wiki?DoubleBraceInitialization
Casebash

30
Прекрасне пояснення, але я не погоджуюся з тим, що статичні внутрішні класи не мають нічого. Дивіться на rwhansen.blogspot.com/2007/07/… про велику зміну моделі побудови, яка сильно залежить від використання статичних внутрішніх класів.
Mansoor Siddiqui

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

9
Приватні статичні вкладені класи також досить корисні: ви хочете їх мати, але не хочете їх виставляти. Як і запис <T> у LinkedList <T>, або AsyncTasks всередині активності (Android) тощо ...
Лоренцо Дематте

150

Я не думаю, що реальна різниця стала зрозумілою у наведених вище відповідях.

Спочатку, щоб правильно встановити умови:

  • Вкладений клас - це клас, який міститься в іншому класі на рівні вихідного коду.
  • Він є статичним, якщо ви оголосите його статичним модифікатором.
  • Нестатичний вкладений клас називається внутрішнім класом. (Я залишаюся з нестатичним вкладеним класом.)

Відповідь Мартіна правильна поки що. Однак актуальним є питання: яка мета оголосити вкладений клас статичним чи ні?

Ви використовуєте статичні вкладені класи, якщо ви просто хочете зберігати свої класи разом, якщо вони належать місцево разом, або якщо вкладений клас використовується виключно вкладному класі. Немає смислової різниці між статичним вкладеним класом і будь-яким іншим класом.

Нестатичні вкладені класи - це інший звір. Подібно до анонімних внутрішніх класів, такі вкладені класи насправді є закриттями. Це означає, що вони захоплюють оточуючу сферу і примірник, що їх додає, і роблять це доступним. Можливо, приклад уточнить це. Дивіться цю заглушку контейнера:

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$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : 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$0 : 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$0. Це встановлюється в конструкторі, який має додатковий параметр типу Container для вказівки примірника, що вкладається. Ви не можете бачити цей параметр у джерелі, але компілятор неявно генерує його для вкладеного класу.

Приклад Мартіна

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

так буде складено до виклику чогось подібного (у байт-кодах)

new InnerClass(outerObject)

Для повноти:

Анонімний клас є прекрасним прикладом нестатичного вкладеного класу, який просто не має асоційованого з ним імені і не може бути посилається пізніше.


17
"Немає семантичної різниці між статичним вкладеним класом і будь-яким іншим класом." За винятком вкладеного класу можна бачити приватні поля / методи батьків, а батьківський клас може бачити приватні поля / методи вкладених.
Бред Купіт

Хіба нестатичний внутрішній клас потенційно не може викликати масових витоків пам'яті? Як у, кожного разу, коли ви створюєте слухача, ви створюєте витік?
G_V

3
@G_V Виразно є потенціал для витоку пам'яті, оскільки екземпляр внутрішнього класу зберігає посилання на зовнішній клас. Чи це актуальна проблема, залежить від того, де і як проводяться посилання на екземпляри зовнішнього та внутрішнього класів.
jrudolph

94

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

OverView

Вкладений клас може бути нестатичним або статичним, і в кожному випадку це клас, визначений в іншому класі . Вкладений клас повинен існувати лише для обслуговування класу , що вкладається, якщо вкладений клас корисний для інших класів (не тільки вкладених), слід оголосити як клас вищого рівня.

Різниця

Нестатичний вкладений клас : неявно пов’язаний із вкладеним екземпляром класу, що містить, це означає, що можна викликати методи та отримати доступ до змінних примірника, що додає. Одне поширене використання нестатичного вкладеного класу - це визначення класу Adapter.

Статичний вкладений клас : не може отримати доступ до екземпляра класу, що охоплює, та викликати на ньому методи, тому його слід використовувати, коли вкладений клас не потребує доступу до екземпляра класу, що закриває. Загальне використання статичного вкладеного класу - це реалізація компонентів зовнішнього об'єкта.

Висновок

Отже, основна відмінність між ними з точки зору дизайну полягає в тому, що нестатичний вкладений клас може отримати доступ до екземпляра класу контейнерів, а статичний не може .


: з вашого висновку "поки статичний не може", навіть не статичні екземпляри контейнера? Впевнені?
VdeX

Загальне використання статичного вкладеного класу - це модель дизайну ViewHolder у RecyclerView та ListView.
Hamzeh Soboh

1
У багатьох випадках коротка відповідь є більш зрозумілою та кращою. Це такий приклад.
Ерік Ван

32

Простіше кажучи, нам потрібні вкладені класи насамперед тому, що Java не забезпечує закриття.

Вкладені класи - це класи, визначені всередині іншого класу, що додається. Вони бувають двох типів - статичні та нестатичні.

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

Внутрішні класи, які називаються некласичними класами, мають доступ до інших членів вищого класу, навіть якщо вони оголошені приватними, поки статичні вкладені класи не мають доступу до інших членів вищого класу.

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

Inner1це наш статичний внутрішній клас і Inner2це наш внутрішній клас, який не є статичним. Ключова різниця між ними, ви не можете створити Inner2екземпляр без Зовнішнього, де ви можете Inner1самостійно створити об'єкт.

Коли ви використовуєте Inner class?

Подумайте про ситуацію, коли 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();

Перевага статичного вкладеного класу полягає в тому, що для його роботи не потрібен об'єкт, що містить клас / топ клас. Це може допомогти вам зменшити кількість об'єктів, які ваша програма створює під час виконання.


3
ти мав на увазі OuterClass.Inner2 inner = outer.new Inner2();?
Ерік Каплун

4
static innerє суперечливістю термінів.
користувач207421

А внутрішні класи також не відомі як "класи, що не є стеками". Не використовуйте форматування коду для тексту, який не є кодом, і не використовуйте його для тексту, який є.
користувач207421

30

Ось ключові відмінності та схожість між внутрішнім класом Java та статичним вкладеним класом.

Сподіваюся, це допомагає!

Внутрішній клас

  • Доступ до зовнішнього класу як екземплярів, так і статичних методів і полів
  • Пов’язаний з екземпляром класу, що вкладається, щоб його інстанціювати спочатку потрібен екземпляр зовнішнього класу (зверніть увагу на нове місце ключового слова):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
  • Неможливо визначити які елементи статичні сам

  • Не може мати клас або інтерфейс декларації

Статичний вкладений клас

  • Неможливо отримати доступ до методів або полів екземплярів зовнішнього класу

  • Не пов’язано з жодним екземпляром укладеного класу. Так, щоб створити його:

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

Подібність

  • Обидва класу Inner можуть отримати доступ навіть закриті поля і методи з зовнішнього класу
  • Крім того , зовнішній клас має доступ до приватним полів і методів з внутрішніх класів
  • Обидва класи можуть мати приватний, захищений або публічний модифікатор доступу

Навіщо використовувати вкладені класи?

Згідно з документацією Oracle є кілька причин ( повна документація ):

  • Це спосіб логічного групування класів, які використовуються лише в одному місці: Якщо клас корисний лише одному другому класу, то логічно вбудувати його в цей клас і тримати їх разом. Введення таких "помічницьких класів" робить їх пакет більш впорядкованим.

  • Це збільшує інкапсуляцію: розгляньте два класи вищого рівня, A і B, де B потрібен доступ до членів A, які в іншому випадку будуть оголошені приватними. Приховуючи клас B у класі A, члени A можуть бути оголошені приватними, і B може отримати доступ до них. Крім того, сам Б може бути прихований від зовнішнього світу.

  • Це може призвести до більш читабельного та легкодоступного коду: Вкладення малих класів у класах верхнього рівня розміщує код ближче до місця його використання.


26

Я думаю, що звичайно дотримується конвенція така:

  • статичний клас у класі вищого рівня - це вкладений клас
  • нестатичний клас у класі вищого рівня - це внутрішній клас , який має ще дві форми:
    • місцевий клас - названі класи, оголошені всередині блоку, як метод або тіло конструктора
    • анонімний клас - безіменні класи, екземпляри яких створюються у виразах та висловлюваннях

Однак, ще кілька моментів, які слід пам’ятати :

  • Класи вищого рівня та статичний вкладений клас семантично однакові, за винятком того, що у випадку статичного вкладеного класу він може статично посилатися на приватні статичні поля / методи свого зовнішнього [батьківського] класу та навпаки.

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

  • Клас "Анонімний" за замовчуванням розширює батьківський клас або реалізує батьківський інтерфейс, і більше немає пропозиції щодо розширення будь-якого іншого класу або впровадження будь-яких інших інтерфейсів. Тому,

    • new YourClass(){}; засоби class [Anonymous] extends YourClass {}
    • new YourInterface(){}; засоби class [Anonymous] implements YourInterface {}

Я відчуваю, що питання, яке залишається відкритим, залишається відкритим, який використовувати і коли? Добре, що в основному залежить від того, з яким сценарієм ви маєте справу, але читання відповіді від @jrudolph може допомогти вам прийняти якесь рішення.


15

Вкладений клас: клас всередині класу

Типи:

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

13

Екземпляр внутрішнього класу створюється, коли створюється екземпляр зовнішнього класу. Тому члени та методи внутрішнього класу мають доступ до членів та методів екземпляра (об'єкта) зовнішнього класу. Коли екземпляр зовнішнього класу виходить за межі, також екземпляри внутрішнього класу припиняють своє існування.

Статичний вкладений клас не має конкретного примірника. Він просто завантажується, коли він використовується вперше (як і статичні методи). Це абсолютно незалежна сутність, чиї методи та змінні не мають доступу до екземплярів зовнішнього класу.

Статичні вкладені класи не поєднуються із зовнішнім об'єктом, вони швидші, і вони не беруть пам'ять heap / stack, оскільки для створення екземпляра такого класу не потрібно. Тому правилом є спробувати визначити статичний вкладений клас із максимально обмеженим діапазоном (приватний> = клас> = захищений> = публічний), а потім перетворити його у внутрішній клас (видаливши "статичний" ідентифікатор) та послабити сфера, якщо це дійсно необхідно.


2
Перше речення неправильне. Там немає такого поняття , як « в разі внутрішнього класу», і екземпляри цього можуть бути створені в будь-який час після того, як зовнішній клас був інстанціювати. Друге речення не випливає з першого речення.
користувач207421

11

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

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

Розглянемо цей приклад:

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" обидва оголошені як "статичний фінал". налаштування nested.innerItem не відбудеться до моменту екземпляру класу (або, принаймні, до моменту введення першого вкладеного статичного елемента), як ви можете самі переконатися, коментуючи та коментуючи рядки, на які я посилаюсь, вище. Те ж не справедливо для "externalItem".

Принаймні, це те, що я бачу в Java 6.0.


10

Терміни вживаються взаємозамінно. Якщо ви хочете бути по-справжньому педантичним щодо цього, тоді ви можете визначити "вкладений клас" для позначення статичного внутрішнього класу, у якого немає екземпляра, що вкладається. У коді у вас може бути щось подібне:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Це насправді не є загальноприйнятим визначенням.


2
"статичний внутрішній" - це суперечність в термінах.
user207421

5
Це не умова, що визначає внутрішній клас як нестатичний вкладений клас, а JLS. docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Lew Bloch

1
І терміни не використовуються як взаємозамінні.
користувач207421

чому статична у наведеному вище прикладі помилка в ide
DeV

10

У разі створення екземпляра екземпляр нестатичного внутрішнього класу створюється з посиланням на об'єкт зовнішнього класу, в якому він визначений. Це означає, що він має вкладений екземпляр. Але екземпляр статичного внутрішнього класу створюється з посиланням на Зовнішній клас, а не з посиланням на об'єкт зовнішнього класу. Це означає, що він не містить інстанції.

Наприклад:

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

1
"статичний внутрішній" - це суперечність в термінах. Вкладений клас є або статичним, або внутрішнім.
користувач207421

9

Я не думаю, що тут багато чого додати, більшість відповідей чудово пояснюють відмінності між статичним вкладеним класом та Внутрішніми класами. Однак врахуйте наступне питання при використанні вкладених класів проти внутрішніх класів. Як згадується в парі відповідей внутрішні класи не можуть бути створені без і екземпляр їх огороджувальних класу , який означає , що вони ТРИМАТИ в покажчик на екземпляр свого класу огороджувальної , що може привести до переповнення пам'яті або переповнення стека виключення з - за факту 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 не може його зібрати, і оскільки він посилається (має вказівник на) зовнішній екземпляр, він також не збирається. Достатньо цих об’єктів у вашому проекті та може не вистачати пам’яті.
Порівняно зі статичними внутрішніми класами, які не вказують на екземпляр внутрішнього класу, оскільки він не пов'язаний з екземплярами, а пов'язаний з класом. Вищенаведена програма може надрукувати " Мене зруйновано! ", Якщо ви зробите Inner class статичним та інстанційнимOuter.Inner i = new Outer.Inner();




8

Аммм ... внутрішній клас - це вкладений клас ... ти маєш на увазі анонімний клас та внутрішній клас?

Редагувати: Якщо ви насправді мали на увазі внутрішнє проти анонімне ... внутрішній клас - це просто клас, визначений у класі, наприклад:

public class A {
    public class B {
    }
}

Тоді як анонімний клас - це розширення класу, визначеного анонімно, тому жоден фактичний "клас не визначається, як у:

public class A {
}

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

Далі редагувати:

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

Існує тонка різниця між статичним і нестатичним вкладеним класом ... в основному нестатичні внутрішні класи мають неявний доступ до полів екземплярів і методів класу, що вкладається (тому вони не можуть бути побудовані в статичному контексті, це буде компілятором помилка). Статичні вкладені класи, з іншого боку, не мають неявного доступу до полів і методів екземплярів, і МОЖУТЬ бути побудовані в статичному контексті.


3
Згідно з документацією Java, існує різниця між внутрішнім класом і статичним вкладеним класом - статичні вкладені класи не мають посилань на свій клас, що вкладається, і використовуються в основному для організаційних цілей. Ви повинні побачити відповідь Джегшемеша для більш поглибленого опису.
mipadi

1
Я думаю, що семантична різниця здебільшого історична. Коли я писав компілятор C # -> Java 1.1, посилання на мову Java була дуже чіткою: вкладений клас є статичним, внутрішній клас - ні (і, таким чином, має це $ 0). У будь-якому випадку це заплутано, і я радий, що це вже не проблема.
Томер Габель

2
JLS визначає "внутрішній клас" у docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3, і тому неможливо мати нестатичний "внутрішній" клас "на Java. "Вкладене" НЕ "просто інший термін, що означає те саме", і НЕ ПРАВИЛЬНО, що "внутрішній клас - це клас, визначений у класі (статичний чи ні)". Це НЕПРАВНА інформація.
Lew Bloch

6

Орієнтація на учнів, які не знають 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?
Відповідь: просто перегляньте специфіку кожного згаданих вище класів.



6

Внутрішній клас і вкладений статичний клас на 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");
        }
    }
}

Посилання: Внутрішній клас та вкладений статичний клас у Java із прикладом


2
"Статичний вкладений клас не може отримати доступ до нестатичного члена (примірника) даних або методу." є неправильним і викликає плутанину . Вони абсолютно мають доступ до інформації приватного примірника, якщо вони створюють екземпляр для доступу до цієї інформації про примірник. У них немає примірника, що складається з прикладу, як у внутрішніх класів, але вони мають доступ до приватних членів екземпляра класу.
TJ Crowder

5

Я думаю, що люди повинні помітити на Плакаті, що: Static Nest Class - лише перший внутрішній клас. Наприклад:

 public static class A {} //ERROR

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

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

 }

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


2
Це все безглуздість. Все це свідчить про те, що внутрішній клас не може містити статичний клас. Частина про "не залежить, який клас він містить" є безглуздою, як і наступне речення.
користувач207421

5

Коли ми оголошуємо статичний клас члена всередині класу, він відомий як вкладений клас верхнього рівня або статичний вкладений клас. Це можна продемонструвати як нижче:

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

"Коли ми оголошуємо статичний клас члена всередині класу, він відомий як вкладений клас верхнього рівня" Це не має сенсу. " Клас вищого рівня - це клас, який не є вкладеним класом." Не існує такого поняття, як "вкладений клас верхнього рівня".
Radiodef

3

Нижче наведено приклад 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()); 

    }

}

3

Я думаю, що жоден із наведених вище відповідей не дає справжнього прикладу для вас різниці між вкладеним класом та статичним вкладеним класом у плані дизайну додатків. І головна відмінність статичного вкладеного класу від внутрішнього класу - це можливість доступу до зовнішнього поля екземпляра класу.

Давайте розглянемо два наступні приклади.

Статичний гніздовий клас: Хорошим прикладом використання статичних вкладених класів є модель побудови ( https://dzone.com/articles/design-patterns-the-builder-pattern ).

Для BankAccount ми використовуємо статичний вкладений клас, в основному тому, що

  1. Статичний екземпляр класу гнізд може бути створений перед зовнішнім класом.

  2. У моделі конструктора будівельник - це клас помічників, який використовується для створення BankAccount.

  3. BankAccount.Builder асоціюється лише з BankAccount. Жодні інші класи не пов'язані з BankAccount.Builder. тому краще їх організувати разом, не використовуючи умовні назви.
public class BankAccount {

    private long accountNumber;
    private String owner;
    ...

    public static class Builder {

    private long accountNumber;
    private String owner;
    ...

    static public Builder(long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Builder withOwner(String owner){
        this.owner = owner;
        return this; 
    }

    ...
    public BankAccount build(){
            BankAccount account = new BankAccount(); 
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            ...
            return account;
        }
    }
}

Внутрішній клас: загальним використанням внутрішніх класів є визначення обробника подій. https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html

Для MyClass ми використовуємо внутрішній клас, головним чином тому, що:

  1. Внутрішній клас MyAdapter потребує доступу до зовнішнього члена класу.

  2. У прикладі MyAdapter асоціюється лише з MyClass. Жоден інший клас не пов'язаний з MyAdapter. тому краще їх організувати разом, не використовуючи конвенцію імен

public class MyClass extends Applet {
    ...
        someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            ...// Event listener implementation goes here...
            ...// change some outer class instance property depend on the event
        }
    }
}

2

Діаграма

введіть тут опис зображення

Основна відмінність між static nestedі non-static nestedкласами , які static nested не має доступ до нестатичних членам зовнішнього класу


0

Перш за все, не існує такого класу, який називається Static class. Статичний модифікатор, який використовується з внутрішнім класом (називається вкладеним класом), говорить про те, що він є статичним членом Зовнішнього класу, а це означає, що ми можемо отримати доступ до нього, як і до інших статичних членів, і не маючи жодного екземпляр Зовнішнього класу. (Яка вигода від статики спочатку.)

Різниця між використанням вкладеного класу та звичайним внутрішнім класом:

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

По-перше, ми можемо створити зовнішній клас, а потім отримати доступ до Внутрішнього класу.

Але якщо клас введений, то синтаксис:

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

Який використовує статичний синтаксис як звичайну реалізацію статичного ключового слова.


1
"... говорить, що це статичний член Зовнішнього класу, що означає ....": Неправильно вважати статичний вкладений клас як "клас класу" Зовнішнього класу, але подібність зі статичними полями та методи закінчуються на цьому. Статичний вкладений клас не "належить" до Зовнішнього класу. Майже у всіх важливих випадках статичний вкладений клас - це вільно стоячий клас верхнього рівня, визначення класу якого вкладено всередині класу Зовнішній клас для зручності упаковки (і, сподіваємось, тому, що між вкладеним класом та Зовнішнім класом існує логічна зв'язок ... хоча такого не потрібно).
scottb

1
"статичний внутрішній" - це суперечність в термінах. Статичні класи існують на першому рівні гніздування, і вони не є внутрішніми класами, за визначенням. Дуже розгублений.
користувач207421

0

Мова програмування Java дозволяє визначити клас в іншому класі. Такий клас називається вкладеним класом і проілюстрований тут:

class OuterClass {
...
class NestedClass {
    ...
    }
}

Вкладені класи поділяються на дві категорії: статичні та нестатичні. Вкладені класи, які оголошені статичними, називаються статичними вкладеними класами. Нестатичні вкладені класи називають внутрішніми класами. Одне, що ми маємо пам’ятати - це нестатичні вкладені класи (внутрішні класи), які мають доступ до інших членів класу, що додається, навіть якщо вони оголошені приватними. Статичні вкладені класи мають доступ до інших членів класу, що додається, лише якщо вони статичні. Він не може отримати доступ до нестатичних членів зовнішнього класу. Як і у випадку методів та змінних класів, статичний вкладений клас асоціюється із його зовнішнім класом. Наприклад, щоб створити об’єкт для статичного вкладеного класу, використовуйте цей синтаксис:

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

Щоб створити внутрішній клас, потрібно спочатку інстанціювати зовнішній клас. Потім створіть внутрішній об’єкт у зовнішньому об'єкті за допомогою цього синтаксису:

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

Чому ми використовуємо вкладені класи

  1. Це спосіб логічного групування класів, які використовуються лише в одному місці.
  2. Це збільшує інкапсуляцію.
  3. Це може призвести до більш читабельного та легкодоступного коду.

Джерело: Підручники Java ™ - Вкладені класи


-1

Різниця полягає в тому, що вкладене оголошення класу, яке також є статичним, може бути екземпляром поза класом, що додає.

Коли у вас є вкладене оголошення класу, яке не є статичним, також відоме як внутрішній клас , Java не дозволить вам інстанціювати його, окрім , що . Об'єкт, створений із внутрішнього класу, пов'язаний з об'єктом, створеним із зовнішнього класу, тому внутрішній клас може посилатися на поля зовнішнього.

Але якщо вона статична, то посилання не існує, до зовнішніх полів не можна отримати доступ (за винятком звичайної посилання, як будь-який інший об'єкт), і тому ви можете інстанціювати вкладений клас самостійно.


1
Це неправда. Існує спеціальний синтаксис для створення внутрішнього класу за межами класу, що додається.
користувач207421

-1

Його досить простий, порівнюючи статичні локальні класи та нестатичні внутрішні класи.
Відмінності:
Статичний локальний клас:
Доступ до лише статичних членів зовнішнього класу.
Неможливо мати статичні ініціалізатори.
Не можна отримати доступ безпосередньо за межами функції, де її оголошено


-2

Я проілюстрував різні можливі правильні сценарії та помилки, які можуть виникнути в коді 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);
                        }*/
                    //}
                }
    }

1
Очевидно, кодова частина. І якщо ви не помітили: ваш приклад коду читати дуже важко. Навіть на своєму величезному настільному моніторі я отримав горизонтальну смугу прокрутки. Спробуйте розмістити свої коментарі вище або нижче того, що вони коментують, а не ззаду .
GhostCat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.