Лекция 07. Вложенные и внутренние классы ####################################################################################### Классификация =========================================================== Вложенные и внутренние классы `````````````````````````````````````````````````````````` Обычные классы в Java относятся к классам **верхнего уровня**. Помимо них в программах могут существовать следующие разновидности **вложенных и внутренних классов:** #. **Статические вложенные классы (static nested classes)**. #. **Внутренние классы (inner classes)**. #. **Локальные классы (local classes)**. #. **Анонимные классы (anonumous classes)**. Для чего используют вложенные и внутренние классы: * Логическая группировка сущностей (все нужное - в одном месте) * Усиление инкапсуляции (''богатый внутренний мир'') * Обеспечение доступа к **private**-членам со стороны некоторых классов (их делают внутренними) * Улучшение читаемости программы (все необходимое ''под рукой'') Статические вложенные классы =========================================================== Вложенные и внутренние классы `````````````````````````````````````````````````````````` **Статические** вложенные классы (СВК) не имеют доступа к нестатическим полям и методам обрамляющего класса. Доступ к нестатическим полям и методам может осуществляться только через ссылку на экземпляр обрамляющего класса. СВК имеют доступ к любым статическим методам внешнего класса, в том числе и к приватным. Польза данных классов заключается в основном в логической группировке сущностей, в улучшении инкапсуляции. В роли СВК могут выступать **интерфейсы** Статические вложенные классы `````````````````````````````````````````````````````````` Статический вложенный класс (СВК) определяется внутри другого класса: .. code-block:: java class A { static class B { } static interface C {} } Такие классы (B или C) никак не связаны с экземплярами класса A. СВК имеет доступ ко всем **static**-членам внешнего класса, включая закрытые. Внешний класс тоже имеет доступ ко всем **static** - членам СВК. Вот так можно создавать экземпляры вложенных статических классов: .. code-block:: java class OuterClass { static class StaticNestedClass { ... } } OuterClass.StaticNestedClass instance = new OuterClass.StaticNestedClass(); Вложенные классы `````````````````````````````````````````````````````````` Интересное использование статических вложенных классов - тестирование приватных статических методов: .. code-block:: java public class ClassToTest { private static void internalMethod() { ... } public static class Test { public void testMethod() { ... } } } Внутренние классы =========================================================== Работа с внутренними классами похожа на работу со статическими вложенными классами, но происходит внутри объектов. .. code-block:: java class A { class B { ... } public B get() { return new B(); } } A.B b=a.get(); Данный класс (B) не может иметь статических элементов, а также перечислений. * Класс **B** известен только внутри класса **A** * Класс **B** имеет доступ к членам класса **A**, но класс **А** не имеет доступа к членам, объявленным внутри **B** * После компиляции: **A.class** и **A$B.class** Каждый экземпляр внутреннего класса связан с экземпляром внешнего класса. Нельзя создать экземпляр внутреннего класса, не создав экземпляр внешнего. Внутренние классы часто используются для предоставления услуг внешним классам. .. code-block:: java class A { class B { private int data; public B(int data) { this.data=data; } public int get() { return data; } } public B getB(int data) { return new B(data); } } .. code-block:: java public class Program { public static void main(String[] args) { A a=new A(); A.B c=a.new B(100); A.B b=a.getB(10); System.out.println(b.get()); System.out.println(c.get()); } } Внешний класс часто содержит метод (вроде **getB**), возвращающий ссылку на объект внутреннего класса. Локальные классы =========================================================== Вложенные классы `````````````````````````````````````````````````````````` Локальные вложенные классы можно создавать прямо в коде методов: .. code-block:: java class A { void method() { class B { ... } B b=new B(); ... } } Ограничения: * они видны только в пределах блока, в котором объявлены; * они не могут быть объявлены как **private, public, protected** или **static**; * они не могут иметь внутри себя статических объявлений (полей, методов, классов); исключением являются константы (**static final**); Локальные классы `````````````````````````````````````````````````````````` Внутренний класс в локальном методе не может использовать локальные переменные внешнего метода до тех пор, пока переменная не будет объявлена как **final** .. code-block:: java class Outer { public void out() { final int val=100; class Inner { public int get() { return val; } } Inner in=new Inner(); System.out.println(in.get()); } } Анонимные классы =========================================================== **Анонимный класс** (anonymous class) - это локальный класс без имени. .. code-block:: java new Thread(new Runnable() { public void run() { ... } }).start(); Использование анонимных классов оправдано в случаях, когда: * тело класса является очень коротким; * нужен только один экземпляр класса; * класс используется в месте его создания или сразу после него; * имя класса не важно и не облегчает понимание кода. В отличие от локальных классов, анонимные должны наследовать существующий класс или интерфейс. Анонимные классы не могут содержать определение статических полей, методов и классов (кроме констант). .. code-block:: java interface Employee { void info(); } public class Program { public static void main(String[] args) { Employee emp=new Employee() { public void info() { System.out.println("Yes!"); } }; emp.info(); } } Вопросы для самоконтроля =============================================