Язык Java позволяет определять класс внутри другого класса. Такие классы называют вложенными классами. Область видимости вложенного класса ограничена областью видимости внешнего класса. Таким образом, если класс В определен внутри класса А, класс В не может существовать независимо от класса А. Вложенный класс имеет доступ к членам (в том числе закрытым) класса, в который он вложен.
Скачать исходники для статьи можно ниже
Однако внешний класс не имеет доступа к членам вложенного класса. Вложенный класс, который объявлен непосредственно внутри области видимости своего внешнего класса, является его членом. Можно также объявлять вложенные классы, являющиеся локальными для блока.
Существует два типа вложенных классов: статические и нестатические. Статический вложенный класс — класс, к которому применен модификатор static.
Поскольку он является статическим, должен обращаться к нестатическим членам своего внешнего класса при помощи объекта. То есть он не может непосредственно ссылаться на нестатические члены своего внешнего класса. Из-за этого ограничения статические вложенные классы используются редко.
Наиболее важный тип вложенного класса — внутренний класс. Внутренний
класс — это нестатический вложенный класс. Он имеет доступ ко всем переменным и методам своего внешнего класса и может непосредственно ссылаться на них так же, как это делают остальные нестатические члены внешнего класса.
Следующая программа иллюстрирует определение и использование внутреннего класса. Класс Outer содержит одну переменную экземпляра outer_x, один метод экземпляра test( ) и определяет один внутренний класс Inner.
// Демонстрация использования внутреннего класса, class Outer { int oater_x = 100; void test(){ Inner inner = new Inner(); inner.display(); } // это внутренний класс class Inner { void display(){ System.out.print In("вывод: outer_x = " + outer_x) ; } } } class InnerClassDemo { public static void main(String args[]) { Outer outer = new Outer(); outer.test(); } }
Это приложение создает следующий вывод.
вывод: outer_x = 100
В этой программе внутренний класс Inner определен в области видимости
класса Outer. Поэтому любой код в классе Inner может непосредственно обращаться к переменной outer_x.
Метод экземпляра display() определен внутри класса Inner. Этот метод отображает значение переменной outer_x в стандартном выходном потоке.
Метод main() экземпляра InnerClassDemo создает экземпляр класса Outer и вызывает его метод test(). Этот метод создает экземпляр класса Inner и вызывает метод display().
Важно понимать, что экземпляр класса Inner может быть создан только внутри области видимости класса Outer. Компилятор Java создает сообщение об ошибке, если любой код вне класса Outer пытается инициализировать класс Inner.
В общем случае экземпляр внутреннего класса должен создаваться содержащей его областью.
Как уже было сказано, внутренний класс имеет доступ ко всем элементам своего внешнего класса, но не наоборот. Члены внутреннего класса известны только внутри области видимости внутреннего класса и не могут быть использованы внешним классом.
// Компиляция этой программы будет невозможна, class Outer { int outer_x = 100; void test() { Inner inner = new Inner(); inner.display(); } // это внутренний класс class Inner { int у = 10; //у- локальная переменная класса Inner void display() { System.out.println("вывод: outer_x = " + outer_x); } } void showy() { System.out.println(у); // ошибка, здесь переменная // у не известна! } } class InnerClassDemo { public static void main(String args[]) { Outer outer = new Outer(); outer.test(); } }
В этом примере переменная у объявлена как переменная экземпляра класса
Inner. Поэтому она неизвестна за пределами класса и не может использоваться методом showy().
Хотя мы уделили основное внимание внутренним классам, определенным в
качестве членов внутри области видимости внешнего класса, внутренние классы можно определять внутри области видимости любого блока.
Например, вложенный класс можно определить внутри блока, определенного методом, или даже внутри тела цикла for, как показано в следующем примере.
// Определение внутреннего класса внутри цикла for. class Outer { int outer_x = 100; void test() { for(int i=0; i<10; i++) { class Inner { void display() { System.out.println("вывод: outer_x = " + outer_x); } } Inner inner = new Inner(); inner.display(); } } } class InnerClassDemo { public static void main(String args[]) { Outer outer = new Outer(); outer.test(); } }
Вывод, создаваемый этой версией программы, показан ниже:
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
вывод: outer_x = 100
Хотя вложенные классы применимы не во всех ситуациях, они особенно удобны при обработке событий.