Внутренний класс связан с экземпляром внешнего класса, и существует два специальных вида: Локальный класс и Анонимный класс . Анонимный класс позволяет нам одновременно объявлять и создавать экземпляр класса, что делает код кратким. Мы используем их, когда нам нужен локальный класс только один раз, поскольку у них нет имени.
Рассмотрим пример из doc , где у нас есть Person
класс:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
и у нас есть метод для печати членов, которые соответствуют критериям поиска:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
, где CheckPerson
такой интерфейс, как:
interface CheckPerson {
boolean test(Person p);
}
Теперь мы можем использовать анонимный класс, который реализует этот интерфейс, чтобы указать критерии поиска как:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
Здесь интерфейс очень прост, а синтаксис анонимного класса кажется громоздким и неясным.
Java 8 ввел термин Функциональный интерфейс , который является интерфейсом только с одним абстрактным методом, поэтому мы можем сказать, что CheckPerson
является функциональным интерфейсом. Мы можем использовать лямбда-выражение , которое позволяет нам передавать функцию в качестве аргумента метода в виде:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
Мы можем использовать стандартный функциональный интерфейс Predicate
вместо интерфейса CheckPerson
, что еще больше сократит объем требуемого кода.