我前几天才知道你可以做到这一点
new Object() {
void hello() {
System.out.println("Hello World!");
}
}.hello();
这对我来说似乎很奇怪。当然,创建的对象的静态类型是Object
,所以没有方法hello()
?它几乎完全没有意义(例如,不可能两次调用hello
。)
我有2个问题。
hello
的唯一方法就是这样。反思怎么样?由于
答案 0 :(得分:16)
有人能指出我解决这个问题的规范部分吗?
这主要在关于Method invocation expressions:
的部分中定义在编译时处理方法调用的第一步是 弄清楚要调用的方法的名称以及哪个类或 用于搜索该名称方法定义的界面。
对于要搜索的类或接口,有六种情况需要考虑, 取决于在左括号之前的形式 的MethodInvocation:
- [...]
- 如果表单为
Primary . [TypeArguments] Identifier
,请让T
成为。{1}} 主表达式的类型。要搜索的类或接口 如果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]);
不要写这样的代码。
答案 1 :(得分:12)
发布后,没有办法从Object
实例获取匿名方法。并且,它使Anonymous classes看起来毫无意义。但是,您可以(我通常会)使用它来实现接口。像,
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进行回调。
答案 2 :(得分:11)
答案 3 :(得分:9)
匿名类是为了懒惰程序员的利益 - 命名事情太难了:)
匿名类非常像本地类。如果一个本地类只是用于创建一个对象,然后只用作超类型,我们可以创建一个更简洁的匿名类。
匿名类是不可否认的(程序员),这很好,因为我们不需要再次引用它。但是,对于编译器而言,该类的名称非常多,并且没有理由将它与显式命名的类区别对待。表达式的静态类型是具体的子类,对象的成员是该类的成员。此功能(能够呼叫hello()
)是否毫无意义?只有当你认为本地课程毫无意义时(实际上很少使用本地课程)。这是example,我使用了这个功能(为了好玩)。
虽然类型是不可否认的,但类型可以通过API自行存活。例如,
Objects.requireNonNull( new Object(){ void hello(){} } ).hello();
即使我们无法命名该类型,也不需要将其命名为可推断的位置。
Collections.singleton( new Object(){ void hello(){} } )
.forEach( o->{ o.hello(); o.hello(); } );
我们可以为那些没有预料到静态类型
的人制作益智游戏 Collections.singleton( new Object(){} ).add( new Object() ); // does not compile! why?