Почему анонимный класс не может реализовать сразу несколько интерфейсов? Просто из-за синтаксиса или есть еще одна причина?

Есть ли внутренняя проблема, почему java-анонимные классы не могут реализовать и подкласс одновременно? Или это просто потому, что синтаксис?

Ответ 1

Внутри есть проблема, почему java-анонимные классы не могут реализовать и подкласс одновременно?

Я считаю, что это 99% из-за синтаксических причин. Параметры типа даже поддерживают типы пересечений (<T extends InterfaceX & InterfaceY>), поэтому я не думаю, что в системе типов возникнут какие-либо "противоречия" или даже осложнения если поддержка такой функции будет добавлена.

Выражение вроде new (InterfaceX & InterfaceY)() { ... } может быть скомпилировано во что-то вроде

interface InterfaceXandY extends InterfaceX, InterfaceY {}

... new InterfaceXandY() { ... }

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


Об одном связанном примечании. Вы можете позволить лямбда-реализации, например, Serializable, выполнив

Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");

См. Как сериализовать лямбда?

Ответ 2

единственный синтаксис, так называемые анонимные классы - это 100% нормальные классы. вы можете достичь фанковых результатов с помощью java.lang.reflect.Proxy и InvocationHandler, было бы самым грязным способом сделать это.

Более простые способы включают объявление класса в методе и просто добавление "орудий",

Ответ 3

Анонимные классы предоставляются как способ быстрого и лаконичного создания класса "один". Ваш вопрос предполагает, что вы пытаетесь использовать свой класс anon несколькими способами (по крайней мере один интерфейс и один расширяется). В этом случае он будет более читабельным и более удобным, если вы продвинете этот класс anon до полного класса.

Это также предотвратит неожиданные побочные эффекты, улучшив инкапсуляцию ваших классов.

Ответ 4

Обнаружен взлом вокруг этого

создайте интерфейс в нижней части файла, который расширяет все интерфейсы, которые вы хотите реализовать, затем создайте анонимный класс, который реализует это.

Ответ 5

По словам Джеймса Госсинга:

Закрытия были исключены из Java изначально из-за времени чем все остальное. В первые дни существования Java отсутствие закрытие было довольно болезненным, и поэтому родились внутренние классы: неудобный компромисс, который пытался избежать ряда трудных вопросы. Но, как это обычно бывает во многих проблемах проектирования, упрощения на самом деле не решали никаких проблем, они просто перенесли их.

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

interface Bar {
   default String getName() { return "Bar"; }
}

Object o = (Comparable<Integer> & Bar) (x,y) -> x > y ? x : y;
Bar b = (Bar) o;
System.out.println(b.getName()); //Bar

Это компилируется и отлично работает в моей последней версии JDK 8 (12 марта 2013 г.). Таким образом, было бы похоже, что на этот раз они больше думали об этой проблеме.