Ранее мы рассмотрели ряд типичных применений внутренних классов. В основном ваш код будет содержать «простые» внутренние классы, смысл которых понять нетрудно. Однако синтаксис внутренних классов скрывает множество других, не столь тривиальных способов их использования: внутренние классы можно создавать внутри метода или даже в пределах произвольного блока. На то есть две причины:
• как было показано ранее, вы реализуете некоторый интерфейс, чтобы затем создавать и возвращать ссылку его типа;
• вы создаете вспомогательный класс для решения сложной задачи, но при этом не хотите, чтобы этот класс был открыт для посторонних.
В следующих примерах рассмотренная недавно программа будет изменена, благодаря чему у нас появятся:
• класс, определенный внутри метода;
• класс, определенный внутри области действия (блока), которая находится внутри метода;
• безымянный класс, реализующий интерфейс;
• безымянный класс, расширяющий класс, у которого отсутствует конструктор по умолчанию;
• безымянный класс, выполняющий инициализацию полей;
• безымянный класс, осуществляющий конструирование посредством инициализации экземпляра (безымянные внутренние классы не могут иметь конструкторы).
Первый пример демонстрирует создание целого класса в контексте метода (вместо создания в контексте другого класса). Такие внутренние классы называются
//• innerclasses/Parce!5.java
// Вложение класса в тело метода.
public class Parcel5 {
public Destination dest(String s) {
class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo;
}
public String readLabelO { return label; } _ Л
}
return new PDestination(s).
}
public static void main(String[] args) { Parcel5 p = new Parcel50; Destination d = p destinationC'TacMaHHH");
}
} ///.-
Теперь класс PDestination является частью метода destination(), а не частью класса Parcel5. Поэтому доступ к классу PDestination возможен только из метода destination(). Обратите внимание на восходящее преобразование, производимое в команде return, — из метода возвращается лишь ссылка на базовый класс Destination, и ничего больше. Конечно, тот факт, что имя класса PDestination находится внутри метода destination(), не означает, что объект PDestination после выхода из этого метода станет недоступным.
Идентификатор PDestination может использоваться для внутренних классов каждого отдельного класса в одном подкаталоге, без порождения конфликта имен.
Следующий пример демонстрирует, как можно вложить внутренний класс в произвольную область действия:
//. innerclasses/Parcel6 java
// Вложение класса в область действия
public class Parcel6 {
private void internalTracking(boolean b) { if(b) {
class TrackingSlip {
private String id;
TrackingSlipCString s) { id = s;
}
String getSlipO { return id; }
}
TrackingSlip ts = new TrackingSlipC'ожидание");
String s = ts getSlipO;
}
// Здесь использовать класс нельзя!
// Вне области видимости.
//! TrackingSlip ts = new Tracki ngSlipCx").
}
public void trackO { internalTracking(true), }
public static void main(String[] args) { Parcel6 p = new Parcel60; p trackO;
}
} ///:-
Класс TrackingSlip вложен в область действия команды if. Это не значит, что
Безымянные внутренние классы
Следующий пример выглядит немного странно:
// innerclasses/Parcel7 java
// Метод возвращает экземпляр безымянного внутреннего класса
public class Parcel7 {
public Contents contents О {
return new Contents О { // Вставить определение класса private int i = 11; public int valueO { return i; } }. // В данной ситуации точка с запятой необходима
}
public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents с = p.contents О;
}
} ///-
Метод contents() совмещает создание возвращаемого значения с определением класса, который это возвращаемое значение и представляет! Вдобавок, этот класс является
Такая необычная форма записи значит буквально следующее: «Создать объект безымянного класса, который унаследован от Contents». Ссылка, которая возвращается при этом из выражения new, автоматически повышается до базового типа Contents. Синтаксис записи безымянного внутреннего класса является укороченной формой записи такой конструкции:
//: innerclasses/Parcel7b.java
II Расширенная версия Parcel7.java
public class Parcel7b {
class MyContents implements Contents { private int i = 11; public int valueO { return i; }
}
public Contents contents О { return new MyContentsО; } public static void main(String[] args) { Parcel 7b p = new Parcel7b(); Contents с = p contentsO;
}
} ///-