实例化类Person时发生了什么?什么是匿名内部类?
abstract class Person {
abstract void eat();
}
class TestAnonymousInner {
public static void main(String args[]) {
Person p = new Person() {
void eat() {
System.out.println("nice fruits");
} // what happens here?
};
p.eat();
}
}
答案 0 :(得分:3)
匿名类实际上只是语法糖。
由于Person
是抽象的,因此您无法直接创建Person
的实例。您必须创建继承Person
的类的实例。这就是抽象类的设计方式。
但是,当您想要使用此类时,有时创建Person
的子类非常不方便。你必须写这样的东西:
class MyClass {
public static void main(String args[]) {
Person p = new PersonSubclass();
p.eat();
}
}
class PersonSubclass extends Person {
void eat() {
System.out.println("nice fruits");
}
}
阅读代码的人必须找到PersonSubclass
的声明才能知道代码的作用。
但是,让我们考虑一下问题的根源:您无法创建Person
实例的原因是因为eat
没有方法体。因此,如果您为eat
创建方法正文,则可以"类型"创建Person
的实例。这就是匿名课程。它们允许您仅通过编写方法体来创建抽象类/接口的实例。这就是为什么上面的代码可以像这样编写的原因:
public static void main(String args[]) {
Person p = new Person() {
void eat() {
System.out.println("nice fruits");
}
};
p.eat();
}
它更短更容易阅读,不是吗?
那么这里到底发生了什么?
编译器为您创建一个Person
的子类,作为封闭类的内部类。在该子类中,有eat
的方法体。内部类被赋予一个非常特殊的名称(我不记得是什么),以便普通代码无法访问它。
P.S。在Java 8中,引入了lambdas。它们只是一种方法的接口的语法糖。但这不适用于抽象类。
答案 1 :(得分:0)
Person
是abstract
所以你无法实例化它;但是通过在实例化期间为abstract
方法注入实现,Person
变为“可实例化”;最后调用了eat()
,结果将是:eat()
=> nice fruits
答案 2 :(得分:0)
实际上匿名内部类是同时声明和实例化类的方法。它们和其他任何类一样,除了没有名字。无论何时声明内部类 匿名,Compiler都会为该类创建内部类。就像这里发生的一样,Compiler创建了一个内部类,如下所示
static class TestAnonymousInner$1 extends Person
{
TestAnonymousInner$1(){}
void eat()
{
System.out.println("nice fruits");
}
}
你可以看到这就像任何其他本地类一样。但由于Person
是abstract
类,因此无法在不扩展的情况下进行实例化。这就是为什么编译器创建内部类的类型为extends Person