调用匿名类的方法

2022-09-01 05:19:13

前几天我了解到你可以这样做

new Object() {
    void hello() {
        System.out.println("Hello World!");
    }
}.hello();

这对我来说真的很奇怪。当然,创建的对象的静态类型是,所以没有方法?这难道不是完全没有意义吗(例如,不可能调用两次)。Objecthello()hello

我对此有2个问题。

  1. 有人能给我指出规范中解决这个问题的部分吗?
  2. 我是否正确地认为,你可以调用的唯一方法就是立即像这样。反射呢?hello

谢谢


答案 1

有人能给我指出规范中解决这个问题的部分吗?

这主要将在有关方法调用表达式的部分中定义

在编译时处理方法调用的第一步是确定要调用的方法的名称以及要搜索该名称的方法定义的类或接口。

对于要搜索的类或接口,有六种情况需要考虑,具体取决于方法调用左括号前面的形式:

  • [...]
  • 如果形式是 ,则设为主表达式的类型。要搜索的类或接口是 if 是类或接口类型,或者 if 的上限是类型变量。Primary . [TypeArguments] IdentifierTTTTT

此处,主表达式类实例创建表达式。因此,要搜索的类型是匿名类型。

我是否正确地认为,你可以调用hello的唯一方法是立即像这样。反射呢?

只要表达式的计算结果为 匿名类型 ,无论是通过像您一样的直接访问,还是通过泛型,您都可以访问(常规访问规则适用)声明的成员。这不仅限于方法。您可以访问字段或类型,尽管它对类型没有那么有用。例如TT

Object var = new Object() {
    class Nested {
    }
}.new Nested();

由于在没有封闭类型的情况下无法引用嵌套类型,因此无法声明该嵌套类型的变量。有用性下降得非常快。(据推测,这也是为什么不能在此匿名类中拥有嵌套类型的原因。static

反射还公开了此方法。生成的匿名类包含此方法,因此您可以检索它并调用它。过程是相同的。实例来自匿名类的事实并不重要。与给定方法名称为字符串时如何调用 Java 方法中介绍的策略相同?

例如

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]);

永远不要写这样的代码。


答案 2

如前所述,没有办法从实例中获取匿名方法。而且,它使匿名类看起来毫无意义。但是,你可以(我通常会)用它来实现一个接口。像这样,Object

static interface Hello {
    void hello();
}
public static void main(String[] args) {
    Hello o = new Hello() {
        public void hello() {
            System.out.println("Hello World!");
        }
    };
    o.hello();
}

或者,更常见的是,使用JFC / Swing和ActionListener进行回调。