Анонимные классы
Анонимный класс объявляется и создаётся одним выражением. Он расширяет ровно один класс либо реализует ровно один интерфейс, но собственного имени и явного конструктора у него нет.
interface RetryPolicy {
boolean shouldRetry(int attempt, Exception error);
}
RetryPolicy policy = new RetryPolicy() {
private int failures;
@Override
public boolean shouldRetry(int attempt, Exception error) {
failures++;
return attempt < 3 && error instanceof IOException;
}
};После new RetryPolicy() { ... } создаются новый класс и его экземпляр. В теле можно объявить поля, методы, instance-блоки и переопределения.
Доступ к окружению
Локальные переменные захватываются только если они final или effectively final. Поля внешнего объекта доступны через Outer.this.
class Screen {
private final String name = "orders";
Runnable listener() {
String event = "refresh"; // effectively final
return new Runnable() {
@Override
public void run() {
System.out.println(Screen.this.name + ": " + event);
}
};
}
}В анонимном классе this — экземпляр анонимного класса. В лямбде this сохраняет значение из окружающего контекста.
Анонимный класс или лямбда
Лямбда подходит функциональному интерфейсу и выражает одну операцию. Анонимный класс нужен, когда есть несколько методов, собственные поля, дополнительный метод или важна отдельная идентичность объекта.
Ограничения:
- нельзя написать явный конструктор;
- тип неудобно повторно использовать и тестировать;
- diamond
<>с анонимным классом ограничивает объявления новых не-переопределяющих методов; - избыточная логика внутри делает место вызова нечитаемым.
На собеседовании
Можно ли реализовать два интерфейса анонимным классом? Не напрямую: выражение имеет один объявленный базовый тип.
Что можно захватить из метода? final или effectively final локальные переменные.
Чем this отличается от лямбды? В анонимном классе это новый объект, в лямбде — окружающий.
Создаётся ли отдельный класс? Да, JVM исполняет экземпляр сгенерированного анонимного класса.
Связано: Функциональные интерфейсы, Виды классов Java, this Java.