Внутренний класс
Внутренний, или вложенный класс (англ. inner class) — в объектно-ориентированном программировании класс, целиком определённый внутри другого класса.
Вложенные классы поддерживаются в языке программирования Java, начиная с версии 1.1, С# и других языках на платформе .NET, а также в языке программирования D и в C++.
Обзор
Экземпляр обычного (внешнего) класса может существовать как независимый объект. Для его существования не требуется обязательное наличие определений других классов или их экземпляров. В случае внутреннего класса, его экземпляр не может существовать без привязки к включающему его классу верхнего уровня либо его экземпляру.
Внутренние классы в языке Java
В Java существуют 4 типа внутренних (inner) классов:
Внутренние (нестатические) классы
Экземпляр внутреннего класса может существовать только тогда, когда существует конкретный экземпляр внешнего класса. Такая логическая связь обусловливает синтаксис создания объектов: сначала создаётся объект внешнего класса, позднее на его основе создаётся объект внутреннего класса.
Внутренние нестатические классы описываются внутри основного внешнего класса. Экземпляры таких классов имеют доступ к public
, protected
, default
и private
полям внешнего класса. А также статическим и нестатическим методам внешнего экземпляра с любыми модификаторами доступа. За счёт того, что экземпляры внутреннего класса всегда логически привязаны к экземплярам окружающего класса, они не могут содержать (хотя могут наследовать от предка) определение статических полей, методов и классов (кроме констант).[1]
Пример объявления внутреннего класса:
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
. Не могут содержать определение (но могут наследовать) статических полей, методов и классов (кроме констант).[2]
Пример:
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 (ссылка на страницу книги)
Примечания
- ↑ Oracle. The Java™ Tutorials. Inner classes . Oracle Documentation. Дата обращения: 12 апреля 2016. Архивировано 22 марта 2016 года.
- ↑ Local Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects) . docs.oracle.com. Дата обращения: 12 апреля 2016. Архивировано 31 марта 2016 года.
Ссылки
- So what are inner classes good for anyway? Архивная копия от 26 апреля 2013 на Wayback Machine
- Внутренние классы в Java