Можно создавать классы внутри других классов – вложенные классы. Они могут работать со всеми членами внешнего класса.
Пример 1. В класс Outer помещено два класса Inner1, Inner2
public class Outer {
int y;
Outer (int x) {// конструктор
y=x;
}
class Inner1 {… public int f1() {return y++;} } //внутренний класс
int g (String s) { // метод
class Inner 2 {…}// локальный внутренний класс
}
}
Компилятор сделает файлы: Outer.class
Outer$Inner1.class
Outer$Inner2.class
Порождение объекта внутри класса Outer: Inner1 i1 = new Inner1 ();
Порождение снаружи: Outer t1 = new Outer ();
Outer.Inner1 i2 = t1. new Inner1(); // t1 -объект класса Outer
Пример 2.
public class Parcel1{
void f() {}
_________________________________________________________________________
class Contents {
private int i =11;
public int value () {return i;}
public Parsel1 outer(){ return Parsel1.this; }//синтаксис!!!
} //ссылка на внешний класс
___________________________________________________________________________
class Destination {//пакетный доступ,может быть и private-тогда снаружи
//нельзя создать объект
private String label;
Destination (String whereTo) {// конструктор
label = where To;
}
String readLabel () {return label;}
}
______________________________________________________________________________
public void ship (String dest) {
Contents c = new Contents ();//создаем объекты внутренних
|
|
//внутри внешних
Destination d = new Destination (dest);
System.out.println (d.readLabel()); //используется метод
//внутреннего класса.
}
public Contents cont () {return new Contents ();}//создаем объект
//внутреннего класса
public static void main (String [] args) {
Parcel1 p = new Parcel1 ();
p.ship (“Тасмания”);
Parcel1 q = new Parcel1();
Parcel1.Contents c = q.cont();//имя внутреннего класса
Parcel1.Destination d = p.new Destination (“Танзания”);
c.outer().f();
}
}// Тасмания
Внутренний класс содержит скрытую ссылку на внешний. Объект внутреннего класса можно создать только в сочетании с объектом внешнего.
Внутренний класс получает доступ к членам внешнего класса.
interface Selector { //для перебора элементов массива (итератор)
boolean end(); // достигнут ли конец последовательности?
Object current(); // обратиться к текущему объекту
void next(); // перейти к следующему объекту
}
public class Sequence { //оболочка для массива Object с размером size
private Object[] items;
private int next = 0;
public Sequence(int size){ items = new Object[size]; }//конструктор
public void add(Оbject x) { // добавление новых объектов к массиву
if (next < items.lenght)
items[next++] = x;
}
private class SequenceSelector implements Selector { //закрытый
//класс, реализующий Selector
private int i = 0; // поле внутреннего класса
public boolean end() {return i == items. length;}//работаем с
//закрытым полем внешнего класса
public void next() { if(i < items. length) i++; }
}
public Selector getSelector() {//вернем Selector!!!!!
return new SequenceSelector();
}
public static void main(String[] args) {
Sequence sequence = new Sequence(10);
for (int i=0; i<10; i++)
Sequence.add(Integer.toString(i)); // создание
//последовательности с заполнением String
Selector selector = sequence.getSelector(); // получили ссылку на
// Selector
while (!selector.end()){//передвигаемся по последовательности
System.out.print(selector.current() + “ ”);
selector.next();
}// while
}// main
|
|
}//class
//0 1 2 3 4 5 6 7 8 9
Внутренний класс может обращаться ко всем полям и методам внешнего.
Зачем нужны внутренние классы ???
Обычно внутренний класс реализует интерфейс или наследует от какого – либо класса. А его код имеет доступ к членам внешнего класса.
Почему не реализовать интерфейс внешним классом?
1) Проектирование. Внутренний класс не обязан реализовывать отношение is – a. (Sequence не является Selector). Кроме того, можно создать еще один внутренний класс Selector, для перебора, например, в обратном направлении (метод reverceSelector () его вернет).
Это дает гибкость-несколько внутренних классов, реализующих один интерфейс.
2) Можно наследовать от нескольких классов: внешний класс от одного, внутренний – от другого (множественное наследование реализации). То есть наследование от многих не интерфейсов, а классов.
3) Можно создать несколько экземпляров внутреннего класса (Selector), которые будут работать одновременно.