logo
Методичка Java

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

Внутренний класс задаётся так же, как вложенный, но только без модификатора static перед именем этого класса:

class ИмяВнешнегоКласса{

тело внешнего класса

class ИмяВнутреннегоКласса{

тело внутреннего класса

}

продолжение тела внешнего класса

}

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

Синтаксис таков:

Сначала идёт создание экземпляра внешнего класса:

ИмяВнешнегоКласса имяОбъекта = new ИмяВнешнегоКласса(параметры);

Затем создаётся нужное число экземпляров внутреннего класса:

ИмяВнешнегоКласса.ИмяВнутреннегоКласса имя1 =

имяОбъекта.new ИмяВнутреннегоКласса(параметры);

ИмяВнешнегоКласса.ИмяВнутреннегоКласса имя2 =

имяОбъекта.new ИмяВнутреннегоКласса(параметры);

и так далее.

Достаточно часто из внутреннего класса необходимо обратиться к объекту внешнего класса. Такое обращение идёт через имя внешнего класса и ссылку this на текущий объект:

ИмяВнешнегоКласса.this

- это ссылка на внешний объект (его естественно назвать родительским объектом). А доступ к полю или методу внешнего объекта в этом случае, естественно, идёт так:

ИмяВнешнегоКласса.this.имяПоля

ИмяВнешнегоКласса.this.имяМетода(список параметров).

К сожалению, в Java, в отличие от языка JavaScript, нет зарезервированного слова parent для обращения к родительскому объекту. Будем надеяться, что в дальнейшем в java будет введён этот гораздо более читаемый и удобный способ обращения к родителю.

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

package java_gui_example;

public class OuterClass {

int a=5;

public OuterClass() {

}

public class InnerClass{

int x=1,y=1;

public class InnerClass2 {

int z=0;

InnerClass2(){

System.out.println("InnerClass2 object created");

};

void printParentClassNames(){

System.out.println("InnerClass.this.x="+InnerClass.this.x);

System.out.println("OuterClass.this.a="+OuterClass.this.a);

}

}

}

InnerClass inner1;

InnerClass.InnerClass2 inner2;

public void createInner() {

inner1=this.new InnerClass();

inner2=inner1.new InnerClass2();

System.out.println("inner1 name="+inner1.getClass().getName());

System.out.println("inner1 canonical name="+

inner1.getClass().getCanonicalName());

}

}

Если в приложении задать переменную типа OuterClass и создать соответствующий объект

OuterClass outer1=new OuterClass();

то после этого можно создать объекты внутренних классов:

outer1.createInner();

Доступ к внешним объектам иллюстрируется при вызове метода

outer1.inner2.printParentClassNames();

Заметим, что при создании внутреннего класса в приложении, а не в реализации класса OuterClass, вместо

InnerClass inner1=this.new InnerClass();

и

InnerClass.InnerClass2 inner2= inner1.new InnerClass2();

придётся написать

OuterClass.InnerClass inner3=outer1.new InnerClass();

OuterClass.InnerClass.InnerClass2 inner4=inner3.new InnerClass2();

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