Перейти к содержимому

Во что компилируется анонимный внутренний класс

  • автор:

#17 – Вложенные и анонимные классы

#17 – Вложенные и анонимные классы

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

Видеоурок

Вложенный класс

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

К примеру, мы разрабатываем класс «Автомобиль». В классе можно прописать множество методов и полей, но описать поведение двигателя или отдельных частей машины бывает куда проще за счёт еще одного дополнительного класса.

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

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

Пример вложенного класса:

class Auto < String model; class Engine < private boolean working = false; public void work () < working = true; System.out.print("Двигатель запущен!"); >> Engine en = new Engine(); > public class Main < public static void main(String[] args) < Auto bmw = new Auto(); bmw.en.work(); >>

Подобный принцип используется во многих классах Java. К пример, если вспомнить класс «System», то в нём также есть вложенный класс и доступ к нему мы получаем за счёт объекта «out»:

// System - основной класс // out - объект на основе вложенного класса // print - метод, что находиться внутри вложенного класса System.out.print("");
Анонимные классы

Анонимные классы — это классы, что не имеют имени и их создание происходит в момент инициализации объекта.

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

Рассмотрим небольшой пример. Предположим что у нас есть интерфейс, который необходимо реализовать. Для реализации можно создать отдельный класс, в нём реализовать интерфейс, далее создать объект на основе класса и через объект ссылаться на методы классы.

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

Пример создания анонимного класса:

Auto car = new Auto() < void flyingMoto () < System.out.print ("Летающий мотоцикл"); >>;

Внутренние и вложенные классы java. Часть 1

Цель статьи: Рассказать о внутренних, вложенных, локальных, анонимных классах. Показать примеры их использования. Написать и протестировать классы в коде на java. Рассказать о свойствах этих классов. Материал предназначен для лучшего понимания безымянных классов, лямбда выражений, адаптеров и многопоточности. Авторское осмысление материала, позволяет посмотреть на уже известные вещи немного иначе. Такой взгляд помогает лучшему понимаю и большей ясности, того что уже известно.

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

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

Начнем с того, что же такое внутренние и вложенные классы. Посмотрим терминологию, встречающуюся в документации и литературе:

В Java существуют 4 типа вложенных (nested) классов:

  1. Статические вложенные классы
  2. Внутренние классы
  3. Локальные классы
  4. Анонимные (безымянные) классы

Существуют четыре категории вложенных классов:

  • статический класс-член (static member class),
  • не статический класс-член (nonstatic member class),
  • анонимный класс (anonymous class)
  • и локальный класс (local class).

Попытаемся разобраться, что же это такое.

Начнем немного отдаленно, так как всё это имеет непосредственное отношение к нашим вопросам. Вспомним объектно-ориентированное программирование. Отношения композиции и наследования.

В своей книге «Java 2 Руководство разработчика» Майкл Морган очень хорошо и подробно описывает взаимосвязи классов и объектов. Мы рассмотрим некоторые из них. Взаимосвязь «это — есть — то» выражается наследованием, а взаимосвязь «имеет часть» описывается композицией.

В наших примерах мы в основном рассматриваем композицию. Так как вложенные классы — это и есть часть чего-то. То есть у нас есть класс оболочка и вложенный класс определенный внутри класса оболочки. Пример композиции: машина имеет двигатель, двери, 4 колеса, корпус. И мы можем описать машину с помощью внутренних (Inner) классов.

Пример такого использования вы можете найти в книге Брюса Эккеля «Философия Java»

/* Пример №1 */ //: c06:Car.java // композиция с использованием открытых объектов // двигатель class Engine < public void start()<>public void rev()<> public void stop()<> > class Wheel< public void inflare(int psi)<>// накачать > // окно class Window< public void rollup()<>// приоткрыть public void rolldown()<>// опустить > // дверь class Door< public Window window=new Window(); public void open()<>//открыть public void close()<>// закрыть > // машина public class Car < public Engine engine = new Engine(); public Wheel[] wheel = new Wheel[4]; public Door left = new Door(), right = new Door();//две двери public Car()< for(int i = 0; ipublic static void main(String[] args) < Car car= new Car(); car.left.window.rollup(); car.wheel[0].inflare(72); >>

Есть некоторое предупреждение автора по использованию кода в таком виде:

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

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

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

Определение вложенных классов:

Класс называется вложенным (nested), если он определен внутри другого класса.

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

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

Пример вложенного класса вы можете увидеть в документации Оракле:

/* Пример №2 */ // class OuterClass < . class NestedClass < . >>

У нас нет, пока что, никакого контекста использования данной конструкции. С таким же успехом вложенный класс мы можем назвать вместо: «Вложенный класс» (NestedClass) — «Внутренний класс» InnerClass. Далее будем разбираться, в чем же отличия, и в каких контекстах используются классы. Брюс Эккель пишет в книге «Философия Java» так:

«Класс называется вложенным (nested), если он определен внутри другого класса»

Документацию Oracle вы можете посмотреть по этой ссылке: >>>

Представим сильно упрощенную аналогию. Вложенные классы в Java напоминают матрешку — одну «куклу» вкладывают в другую. Например, если взять две куклы — большую и маленькую — и вложить маленькую в большую, то маленькая будет вложенным классом для большой. Такая ситуация отражает только «вложенность», но не отражает «взаимодействия».

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

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

Терминология:

Существует четыре категории вложенных классов:

  1. Статические вложенные классы и не статические вложенные классы. Вложенные классы, объявленные статически, называются вложенными статическими классами.
  2. Внутренние классы — когда объект внутреннего класса связан с объектом обрамляющего класса. Не статические вложенные классы называются внутренними классами, если они связанны с внешним классом.
  3. Локальные классы — объявленные внутри блока кода и не являющиеся членом обрамляющего класса. В этом случае можно рассматривать класс как локальную переменную типа класс.
  4. Анонимные классы – наследуемые, от какого либо класса, классы в которых при объявлении не задано имя класса.

Причины использования вложенных классов такие. Если класс полезен только для одного другого класса, то вполне логично встроить его в этот класс и хранить их вместе. Использование вложенных классов увеличивает инкапсуляцию. Рассмотрим два класса верхнего уровня, A и B, где B нужен доступ к членам, которые иначе были бы объявлены закрытыми.
«`java
/* Пример №3 */
//
class A …
class B …
>
>
«`

Скрывая класс «B» в пределах класса «А», члены класса «А» могут быть объявлены закрытыми, и «B» может получить доступ к ним. Кроме того, сам «B» может быть скрыт от внешнего мира.

Продемонстрируем это в коде:
«`java
/* Учебный пример №4 */
package innernested;

/**
*
* author Ar20L80
*/
public class A private static int iPrivVar;
class B void setPrivateOfA(int var)
A.iPrivVar = var;
>
>
>
«`
Использование вложенных классов приводит к более читабельному и поддерживаемому коду: Размещение класса ближе к тому месту, где он будет использован, делает код более читабельным.

Статические Вложенные Классы
Static Nested Classes

Причины использования статических вложенных классов такие.

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

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

Статические вложенные классы не имеют ограничений по объявлению своих данных и полей как static.

Из вложенного статического класса мы не имеем доступа к внешней не статической переменной внешнего класса.

Приведенный ниже код демонстрирует это:
«`java

/*
Учебный пример №5
Статические вложенные классы

Попытка доступа к не статической переменной
внешнего класса Outer2 через обращение из вложенного статического класса Nested2
*/
package nested;

/**
*
* author Ar20L80
* 20.03.2016
*/
public class Outer2 public int pubOutVar; // переменная не статическая и мы не имеем к ней доступа
// из внутреннего статического класса
private int prOutVar;
public Outer2()<>// конструктор внешнего класса

static class Nested2 public static int pub_innVar; // тут все в порядке
public Nested2() <> // конструктор вложенного класса

int getOuterPublicVariable()
return Outer2.this.pubOutVar; // ошибка
return Outer2.pubOutVar; // ошибка
>

int getOuterPrivateVariable()
return Outer2.this.prOutVar; // ошибка
return Outer2.prOutVar; // ошибка
>

Вывод: Мы не имеем доступа к не статическому полю внешнего класса, через статический контекст вложенного класса. Это подобно тому, как мы не имеем доступа из статического метода к нестатическим переменным класса. Точно также из статического вложенного класса мы не имеем доступа к нестатическим переменным внешнего класса.

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

Приведенный ниже фрагмент кода демонстрирует это:
«`java

/*
Учебный пример №6
Статические вложенные классы

Демонстрация доступа к «приватной» статической переменной
внешнего класса из внутреннего статического класса
20.03.2016
*/
package nested;

/**
*
* author Ar20L80
*/
public class Outer3 private static int prStOuterVar;
public Outer3()<>

static class Nested3 // Nested
<
int getStaticOuterVar()
return Outer3.prStOuterVar; // ok
>
void setStaticOuterVariable(int var)
Outer3.prStOuterVar = var; // ok
>
>
public static void main(String[] args) Outer3.Nested3 nestedObj = new Outer3.Nested3(); // экземпляр класса внутренний

System.out.println(«nestedObj.getStaticOuterVar() = „+nestedObj.getStaticOuterVar());//статическая переменная внешнего класса из экземпляра внутреннего

// устанавливаем через экземпляр внутреннего класса
nestedObj.setStaticOuterVariable(77);
System.out.println(“Outer3.prStOuterVar = „+ Outer3.prStOuterVar);
>
>
/*
Вывод программы:
nestedObj.getStaticOuterVar() = 19
Outer3.prStOuterVar = 77
*/
«`

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

Майкл Морган. «Java 2. Руководство разработчика» ISBN 5-8459-0046-8
Брюс Эккель. «Философия Java.» ISBN 5-272-00250-4
Герберт Шилдт «Java. Полное руководство. 8-е издание.» ISBN: 978-5-8459-1759-1

Все вопросы, комментарии, дополнения, критика приветствуются.

Для вашего комфорта, я создал репозиторий на github.
Теперь вы можете скачать актуальные версии кода, для ваших экспериментов, тестов и изучения:
https://github.com/vvm64/InnerAndNestedCl

PS. Нумерация материалов может не соответствовать нумерации материалов в статье.

Продолжение следует…
Часть 2 >>>

  • Программирование
  • Java
  • Проектирование и рефакторинг
  • ООП

Pro Java

Анонимный класс – это локальный класс без имени. Можно объявить анонимный (безымянный) класс, который может расширить (extends) другой класс или реализовать (implements) интерфейс. Объявление такого класса выполняется одновременно с созданием его объекта посредством оператора new.

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

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

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

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

Теперь рассмотрим на практике простой пример:

AN0001

На примере слева красными рамками обозначены фрагменты кода где объявляются анонимные классы. Первый имплементирует интерфейс Iout, второй расширяет класс External. Обратите внимание на двоеточие после фигурных скобок закрывающих объявление класса , оно является обязательным, так как по существу объявление анонимного класса представляет собой выражение . Это означает, что его можно записать как часть большего выражения, например вызова метода . Я привел достаточно простые примеры, хотя синтаксис все равно может показаться сложным. И начал я с объявления анонимного класса реализующего интерфейс Iout, так как на этом примере более легко понять почему анонимные классы называются анонимными – так как у них нет имени. Как вы помните невозможно создать экземпляр интерфейса, поскольку он является полностью абстрактным классом, а тут мы создаем класс реализующий интерфейс, но у этого класса нет имени и ссылку на этот анонимный класс мы присваиваем интерфейсной переменной iout. Надеюсь все просто? Ни кто не запутался?

Во втором же примере не все так прозрачно, так как может показаться что у класса все же есть имя External, но это не так. Класс по прежнему анонимный, так как он расширяет класс External и не является экземпляром класса External, хотя ссылка на этот анонимный класс присвоена переменной класса External, что является нормальным и обычным. Надеюсь что опять ни кто не запутался 🙂

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

Первую строку выводит метод outPrint(), другие – extPrint().

Как видите, синтаксис определения анонимного класса включает так же и создание экземпляра этого класса используя для этого ключевое слово new, за которым следует имя супер класса или интерфейса и затем определение самого анонимного класса в фигурных скобках за которыми следует двоеточие. Если имя, следующее за ключевым словом new, это имя класса, то анонимный класс является подклассом этого класса. Если имя, следующее за ключевым словом new, представляет собой интерфейс, то анонимный класс реализует этот интерфейс и расширяет класс Object . Данный синтаксис не позволяет указать секции extends, implements или имя класса. В следствии этого анонимный класс может реализовать только один интерфейс .

AN0003

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

Вывод у программы следующий:

AN0004

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

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

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

Анонимные классы, так же как и локальные, имеют доступ к локальным переменным своего блока кода которые объявлены как final или они должны быть effectively final .

Анонимные классы имеют доступ ко всем членам своего вешнего класса.

Если в анонимном классе объявлена переменная с таким же именем как и в окружающем классе, то она затеняет переменную окружающего класса.

Анонимный класс не может определять статические поля, методы или классы, кроме констант static final. Интерфейс не может быть объявлен анонимно, потому что нет способа реализовать интерфейс без имени. Так же как и локальные классы, анонимные классы не могут быть public, private, protected или static.

В анонимном классе вы не можете объявить статические инициализационные блоки.

В анонимном классе вы не можете объявить интерфейс.

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

В анонимном классе вы можете объявить:

  • Поля
  • Дополнительные методы (даже если этих методов нет в классе родителе)
  • Инициализационные блоки экземпляра
  • Локальные классы

Ну и теперь рассмотрим примеры всех вышеприведенных утверждений.

AN0006

Начнем пожалуй с этого 🙂 то есть с .this. В Принципе это можно было еще на первом примере показать, но чет запамятовал. В общем первый пример мутировал в текущий. Я добавил строку str в класс Outer и затем обратился к ней из анонимного класса. Эти две строки подсвечены желтым.

Теперь у программы такой вывод:

AN0007

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

А теперь попробуем смоделировать конструктор анонимного класса 🙂

AN0008

Чтобы смоделировать конструктор в анонимном классе нам будет необходим класс от которого будет наследоваться наш анонимный класс. С анонимным классом имплементирующем интерфейс такой номер не прокатит, так как у интерфейсов нет конструкторов.

Нам так же необходимо чтобы у родительского класса был конструктор. И тогда, как уже говорилось, все аргументы которые будут указаны в круглых скобках при создании анонимного класса будут передаваться конструктору родительского класса, но так же будут доступны и в анонимном. Причем даже если в родительском классе эти аргументы используются только в конструкторе и ни где более, то есть не сохраняются в полях родительского класса, эти аргументы все равно будут доступны в анонимном классе. Но они должны быть переданы в конструктор с модификатором final или быть effectively final .

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

Вывод программы представлен ниже:

AN0009

Как видно из вывода программы аргумент i переданный в конструктор суперкласса Base доступен как в конструкторе суперкласса, так и в инициализаторе и методах анонимного класса, который в данном случае является и наследником класса Base и так же внутренним его классом. Именно поэтому ему доступно private static поле i. Я умышленно дал одинаковые названия аргументу и полю, чтобы продемонстрировать области видимости переменных и полей.

И еще один пример на тему эмулирования конструкторов в анонимных классах:

AN0010

AN0011

AN0012

В это программе не используются статические методы и поля для того чтобы продемонстрировать доступ к полям экземпляров в классах Base и External. По существу у нас есть два анонимных класса. Анонимный класс в классе Base является и вложенным в него и его же наследником, а в классе External анонимный класс является наследником класса Base и внутренним для класса External. Именно по этому в первом случае анонимный класс имеет доступ к private полю str класса Base, а во втором не имеет и использует для доступа к нему унаследованный метод getStr(). Собственно из вывода программы видно как она работает 🙂

AN0013

Я немного изменил предыдущий пример, чтобы продемонстрировать наследование. Теперь класс External является наследником класса Base. И поэтому от туда был убран метод getThis() и добавлены конструкторы. Класс Main тоже претерпел небольшие изменения, туда была добавлена одна строка.

println ( «e.getStr #000000» size=»2″> + e . getStr ()) ;

Обратите внимание что анонимный класс находящийся внутри класса External так же является наследником класса Base.

AN0014

AN0015

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

Уровень 24. Ответы на вопросы к собеседованию по теме уровня

Java-университет

Уровень 24. Ответы на вопросы к собеседованию по теме уровня - 1

  1. Во что компилируются анонимные внутренние классы? Анонимные внутренние классы компилируются в файлы внешнийКласс$n.class . На месте внешнего класса, соответственно, название обрамляющего класса, внутри которого описывается анонимный внутренний класс. На месте n число от 1 до количества анонимных классов.
  2. Можно ли наследовать внутренние классы? Наследовать внутренние классы от других — можно. Наследование от внутреннего класса получается чуть сложнее, чем обычное, так как конструктор внутреннего класса связывается со ссылкой на окружающий внешний объект. Проблема состоит в том, что «скрытая» ссылка на объект объемлющего внешнего класса должна быть инициализирована, а в производном классе больше не существует объемлющего объекта по умолчанию. Для явного указания объемлющего внешнего объекта применяется специальный синтаксис:
 //: innerclasses/InheritInner.java // Наследование от внутреннего класса. class WithInner < class Inner <>> public class InheritInner extends WithInner.Inner < //! InheritInner() <>// He компилируется InheritInner(WithInner wi) < wi.super(); >public static void main(String[] args) < WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); >> 
 import java.awt.event.WindowListener; public class TestExtendAnonym < private interface MyInterface extends Runnable, WindowListener < >Runnable r = new MyInterface() < . //Пример того как реализовать 2 и более интерфейса в анонимном классе >; > 
 //: innerclasses/BigEgg.java // Внутренний класс нельзя переопределить // подобно обычному методу, import static net.mindview.util.Print.*; class Egg < private Yolk y; protected class Yolk < public Yolk() < print("Egg.Yolk()"); >> public Egg() < print("New Egg()"); y = new Yolk(); >> public class BigEgg extends Egg < public class Yolk < public Yolk() < print("BigEgg.Yolk()"); >> public static void main(String[] args) < new BigEgg(); >> 

Вывод:

 New Egg() Egg.Yolk() 
  1. он имеет доступ только к финальным полям и аргументам обрамляющего метода, а также ко всем полям обрамляющего класса, в том числе приватным и статическим;
  2. локальный класс виден и может создаваться только в блоке, в котором описан;
  3. у локального класса не ставится модификатор доступа;
  4. не может иметь статических полей, методов, классов (за исключением финальных);
  5. локальный класс, объявленный в статическом блоке может обращаться только к статическим полям внешнего класса.

Но! Начиная с Java8 мы можем обращаться в локальных классах к не финальным локальным переменным, если они не были изменены до момента инициализации класса. Также теперь стало возможным обращение к не финальным параметрам метода.

 public class PrivateConst < private PrivateConst() <>public class InnerClass < public void f()< System.out.println("hello"); >> > 

Напрямую, в другом классе (вне обрамляющего), конечно, создать объект InnerClass следующим способом не получится:

 PrivateConst.InnerClass priv = new PrivateConst().new InnerClass(); 

Но! Что если у нас есть метод, возвращающий экземпляр

 PrivateConst:public class PrivateConst < private static PrivateConst instance; private PrivateConst() <>public static PrivateConst getInstance() < instance = new PrivateConst(); return instance; >public class InnerClass<> > 

Добавить комментарий

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