Может ли кто-нибудь указать мне на часть спецификации, которая обращается к этому вопросу?
Это будет главным образом определено в секции относительно Method invocation expressions:
Первым шагом в обработке вызова метода во время компиляции, чтобы выяснить, имя метода, который будет вызван, и какой класс или интерфейс для поиска определений методов этого имени.
Для класса или интерфейса для поиска, есть шесть случаев, чтобы рассмотреть, в зависимости от формы, которая предшествует левую скобку в MethodInvocation:
- [...]
- Если форма
Primary . [TypeArguments] Identifier
, то пусть T
будет тип первичного выражения. Класс или интерфейс для поиска : T
, если T
- тип класса или интерфейса или верхняя граница T
, если T
- это переменная типа.
Здесь Первичное выражение является class instance creation expression. Таким образом, для поиска используется анонимный тип.
Я правильно понял, что единственный способ, которым вы можете позвонить, - это сразу вот так. Как насчет отражения?
До тех пор пока выражение анонимного типа T
, будь то посредством прямого доступа, как у вас есть, или через дженериков, у вас есть доступ (регулярные правила доступа применяются) к членам, которые T
заявляет. Это не ограничивается методами. Вы можете получить доступ к полям или типам, хотя это не так полезно для типов. Например,
Object var = new Object() {
class Nested {
}
}.new Nested();
Поскольку нет никакого способа, чтобы обратиться к вложенному типу без типа ограждающей, вы не можете объявить переменную этого вложенного типа. Полезность снижается очень быстро. (Предположительно, поэтому у вас не может быть вложенного типа static
в этом анонимном классе.)
Отражение также раскрывает этот метод. Созданный анонимный класс содержит этот метод, поэтому вы можете его восстановить и вызвать. Процесс тот же. Тот факт, что экземпляр из анонимного класса не имеет значения. Используется та же стратегия, что и в приложении How do I invoke a Java method when given the method name as a string?.
Например,
Object ref = new Object() {
public void method() {
System.out.println("hidden");
}
};
Class<?> anonymousClass = ref.getClass();
Method method = anonymousClass.getMethod("method");
method.invoke(ref, new Object[0]);
Никогда не писать код, как это.
[JLS-15.9.5. Анонимные объявления классов] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5) –
Вы должны быть в состоянии добраться до него через отражение. Но да, это почти совершенно бессмысленно.Если вы хотите вызвать методы, вы обычно реализуете интерфейс в своем анонимном классе. – Thilo
Ну, если вы создаете анонимный класс более определенного типа (например, анонимную реализацию * интерфейса *), вы можете удерживать ссылку в переменной, которая позволит вам называть эти методы по своему усмотрению. –