Автор: Widowmaker1984

Вопросы 55, 62-68 (вложенные классы)

"Что такое статический класс, какие особенности его использования?"
"Какие типы классов бывают в java (вложенные… и.т.д.)"
"Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции."
"Каким образом из вложенного класса получить доступ к полю внешнего класса?"
"Какие особенности создания вложенных классов: простых и статических."
"В чем разница вложенных и внутренних классов?"
"Какие классы называются анонимными?"
"Каким образом можно обратиться к локальной переменной метода из анонимного класса, объявленного в теле этого метода? Есть ли какие-нибудь ограничения для такой переменной?"


1. Кроме "обычных" классов верхнего уровня (top level classes) в Java можно объявлять т.н. вложенные классы. Это классы, который объявлены внутри объявления другого класса.

1.1. Вложенные классы делятся на статические (static nested classes) и нестатические (non-static). Нестатические вложенные классы имеют другое название — внутренние классы (inner classes). Внешний класс (outer class) по отношению к ним можно назвать обрамляющим классом.

1.1.1. Итого, "внутренние" (inner) классы — это подмножество "вложенных" (nested), а именно не-статические "вложенные" классы. Тем не менее часто под "внутренними" классами подразумеваются все "вложенные".

скрытый текст1.2. Использование вложенных классов всегда приводит к некоторому нарушению инкапсуляции — вложенный класс может обращаться к закрытым членам внешнего класса (но не наоборот!). По сути внутренний класс всего лишь является специализированным членом внешнего класса.

2. Статические вложенные классы, не имеют доступа к нестатическим полям и методам обрамляющего класса, в чем аналогичны объявленным внутри класса статическим методам. Доступ к нестатическим полям и методам может осуществляться только через ссылку на экземпляр обрамляющего класса. Но static nested классы имеют доступ к любым статическим методам внешнего класса, в том числе и к приватным.

2.1. Польза данных классов заключается в основном в логической группировке сущностей и улучшении инкапсуляции. Другое интересное использование статических вложенных классов - тестирование приватных статических методов.

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

2.2.1. Поэтому объявление вида public interface ImNonStaticInterface будет интерпретироваться в виде public static interface ImNonStaticInterface. То есть неявно будет добавлен модификатор static.

2.3. Статический класс — это всегда вложенный класс. К классу высшего уровня модификатор static неприменим.

3. Нестатические вложенные классы называют также внутренними классами (inner). Внутренний класс имеет доступ ко всем переменным и методам своего внешнего класса и может непосредственно ссылаться на них. Он ассоциируется не с самим внешним классом, а с его экземпляром.

3.1. Объект внутреннего класса связан с внешним объектом-создателем и может обращаться к его членам без каких-либо дополнительных описаний. При совпадении имен во внутреннем и внешнем классе, доступ к полю или методу экземпляра обрамляющего класса можно получить через следующую конструкцию: [Имя обрамляющего класса].this.[Имя члена класса].

3.2. Внутренние классы в Java делятся на три вида:
- внутренние классы-члены (member inner classes);
- локальные классы (local classes);
- анонимные классы (anonymous classes).

4. Внутренний класс-член (member inner classes) может иметь любой модификатор доступа (private, package—private, protected, public).

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

5. Локальные классы (local classes) определяются в блоке кода. На практике чаще всего объявление происходит в методе некоторого другого класса. Хотя объявлять локальный класс можно и внутри статических или нестатических блоков инициализации.

5.1. Как и member классы, локальные классы ассоциируются с экземпляром обрамляющего класса и имеют доступ к его полям и методам. Кроме этого, локальный класс может обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором final.

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

5.2. У локальных классов есть множество ограничений:
- они видны только в пределах блока, в котором объявлены;
- они не могут быть объявлены как private, public, protected или static;
- при этом могут быть помечены как abstract или final, но не оба одновременно;
- они не могут иметь внутри себя статических объявлений (полей, методов, классов); исключением являются константы (static final);

6. Анонимный класс (anonymous class) - это локальный класс без имени. Так как анонимный класс является локальным классом, он имеет все те же ограничения, что и локальный класс. Они могут быть созданы двумя путями:
- как наследник определённого класса;
- как реализация определённого интерфейса.

6.1. Основное ограничение при использовании анонимных классов — это невозможность описания конструктора, так как класс не имеет имени.

6.2. Любой анонимный внутренний класс может реализовать только один интерфейс. Так же, за один раз можно либо расширить класс, либо реализовать интерфейс, но не одновременно.

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

Комментарии


Лучшее   Правила сайта   Вход   Регистрация   Восстановление пароля

Материалы сайта предназначены для лиц старше 16 лет (16+)