Interested Article - Внутренний класс

Внутренний , или вложенный класс ( англ. inner class) — в объектно-ориентированном программировании класс , целиком определённый внутри другого класса.

Вложенные классы поддерживаются в языке программирования Java , начиная с версии 1.1, С# и других языках на платформе .NET, а также в языке программирования D и в C++ .

Обзор

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

Внутренние классы в языке Java

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

Внутренние (нестатические) классы

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

Внутренние нестатические классы описываются внутри основного внешнего класса. Экземпляры таких классов имеют доступ к public , protected , default и private полям внешнего класса. А также статическим и нестатическим методам внешнего экземпляра с любыми модификаторами доступа. За счёт того, что экземпляры внутреннего класса всегда логически привязаны к экземплярам окружающего класса, они не могут содержать (хотя могут наследовать от предка) определение статических полей, методов и классов (кроме констант).

Пример объявления внутреннего класса:

class OuterClass { private int outerField; class InnerClass { int getOuterField() { return OuterClass.this.outerField; // эта строчка кода демонстрирует концепцию замыкания. } } } 

Создание описанного класса можно описать следующим блоком кода: OuterClass.InnerClass inner = new OuterClass().new InnerClass();

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

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

Пример объявления вложенного статического класса:

class OuterClass { private int outerField; static int staticOuterField; static class StaticInnerClass { int getOuterField() { return OuterClass.this.outerField; // эта строчка кода приведёт к ошибке компиляции. } int getStaticOuterField() { return OuterClass.staticOuterField; // эта строчка кода корректна. } } } 

Создание описанного статического вложенного класса можно описать следующим блоком кода: OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();

Локальные классы

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

Пример:

class OuterClass { private int outerField; void methodWithLocalClass(final int finalParameter) { int notFinalVar = 0; notFinalVar++; class InnerLocalClass { void getOuterField() { int a = notFinalVar; // эта строчка кода приведёт к ошибке компиляции. no-final переменные вне контекста недоступны. int b = OuterClass.this.outerField; // эта строчка кода демонстрирует обращение члену обрамляющего класса. } int getParameter() { return finalParameter; // эта строчка кода демонстрирует обращение к final переменной вне контекста. } } } } 

Создание описанного локального класса возможно только внутри самого метода строго ниже кода объявления самого класса. Пример кода создания: InnerLocalClass innerLocal = new InnerLocalClass();

Анонимные (безымянные) классы

Декларируются внутри методов основного класса. Могут быть использованы только внутри этих методов. В отличие от локальных классов, анонимные классы не имеют названия. Главное требование к анонимному классу - он должен наследовать существующий класс или реализовывать существующий интерфейс. Не могут содержать определение (но могут наследовать) статических полей, методов и классов (кроме констант). Пример:

class OuterClass { /** * При определении анонимного класса применен полиморфизм — переменная listener * содержит экземпляр анонимного класса, реализующего существующий * интерфейс ActionListener. **/ void methodWithAnonymousClass(final int interval) { ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("Эта строка выводится на экран каждые " + interval + " секунд."); } }; Timer t = new Timer(interval, listener); // объект анонимного класса использован внутри метода. t.start(); } } 

Внутренние классы в других языках программирования

В PHP 7 есть механизм описания анонимных классов, однако, в отличие от Java, анонимные классы не обязаны наследовать существующий класс или реализовывать существующий интерфейс , что достигается благодаря динамической природе языка. Пример:

// Pre PHP 7 code class Logger { public function log($msg) { echo $msg; } } $util->setLogger(new Logger()); // PHP 7+ code $util->setLogger(new class { public function log($msg) { echo $msg; } }); 

См. также

Литература

Cay S. Horstmann and Gary Cornell, Core Java , eighth edition (Volume I). Prentice Hall, 2003. ISBN 978-0132354769 ()

Примечания

  1. Oracle. (неопр.) . Oracle Documentation . Дата обращения: 12 апреля 2016. 22 марта 2016 года.
  2. (неопр.) . docs.oracle.com. Дата обращения: 12 апреля 2016. 31 марта 2016 года.

Ссылки

Same as Внутренний класс