Вопрос-ответ

How are anonymous inner classes used in Java?

Как анонимные внутренние классы используются в Java?

В чем польза анонимных классов в Java? Можем ли мы сказать, что использование анонимного класса является одним из преимуществ Java?

Переведено автоматически
Ответ 1

Под "анонимным классом", я так понимаю, вы подразумеваете анонимный внутренний класс.

Анонимный внутренний класс может оказаться полезным при создании экземпляра объекта с определенными "дополнениями", такими как переопределяющие методы, без необходимости фактического создания подкласса класса.

Я обычно использую это как ярлык для подключения прослушивателя событий:

button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// do something
}
});

Использование этого метода немного ускоряет кодирование, поскольку мне не нужно создавать дополнительный класс, который реализует ActionListener - я могу просто создать экземпляр анонимного внутреннего класса, фактически не создавая отдельный класс.

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

Ответ 2

Анонимные внутренние классы фактически являются замыканиями, поэтому их можно использовать для эмуляции лямбда-выражений или "делегатов". Например, возьмем этот интерфейс:

public interface F<A, B> {
B f(A a);
}

Вы можете использовать это анонимно для создания первоклассной функции в Java. Допустим, у вас есть следующий метод, который возвращает первое число, большее i в данном списке, или i, если ни одно число не больше:

public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}

И тогда у вас есть другой метод, который возвращает первое число, меньшее, чем i в данном списке, или i, если ни одно число не меньше:

public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}

Эти методы практически идентичны. Используя первоклассную функцию типа F, мы можем переписать их в один метод следующим образом:

public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}

Вы можете использовать анонимный класс для использования метода firstMatch:

F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);

This is a really contrived example, but its easy to see that being able to pass functions around as if they were values is a pretty useful feature. See "Can Your Programming Language Do This" by Joel himself.

A nice library for programming Java in this style: Functional Java.

Ответ 3

Анонимный внутренний класс используется в следующем сценарии:

1.) Для переопределения (подклассов), когда определение класса невозможно использовать, за исключением текущего случая:

class A{
public void methodA() {
System.out.println("methodA");
}
}

class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}

2.) Для реализации интерфейса, когда реализация интерфейса требуется только для текущего случая:

interface InterfaceA{
public void methodA();
}

class B{
InterfaceA a = new InterfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}

3.) Анонимный внутренний класс, определенный аргументом:

interface Foo {
void methodFoo();
}

class B{
void do(Foo f) { }
}

class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
Ответ 4

Иногда я использую их как синтаксический взлом для создания экземпляра Map:

Map map = new HashMap() {{
put("key", "value");
}};

против

Map map = new HashMap();
map.put("key", "value");

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

java