Java 实例化抽象类时发生了什么?什么是匿名内部类?
实例化类Person时发生了什么?什么是匿名内部类Java 实例化抽象类时发生了什么?什么是匿名内部类?,java,anonymous-inner-class,Java,Anonymous Inner Class,实例化类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
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();
}
}
Person
是抽象的
,因此不能实例化它;但是通过在实例化过程中为抽象
方法注入一个实现,Person
成为“可实例化的”;最后调用eat()
,结果将是:eat()
=>美味水果
匿名类实际上只是语法糖
由于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");
}
}
public static void main(String args[]) {
Person p = new Person() {
void eat() {
System.out.println("nice fruits");
}
};
p.eat();
}
阅读您的代码的人必须找到PersonSubclass
的声明才能知道代码的功能
但是让我们考虑一下问题的根源:无法创建Person
实例的原因是eat
没有方法体。因此,如果您为eat
创建一个方法体,您可以“有点”创建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");
}
}
public static void main(String args[]) {
Person p = new Person() {
void eat() {
System.out.println("nice fruits");
}
};
p.eat();
}
它短得多,也容易读,不是吗
那么这里到底发生了什么
编译器为您创建一个子类Person
,作为封闭类的内部类。在该子类中,有eat
的方法体。内部类被赋予了一个非常特殊的名称(我不记得是什么),因此普通代码无法访问它
另外,在Java8中,引入了lambda。对于只有一种方法的接口,它们同样是语法糖。但这不适用于抽象类。实际上,匿名内部类是同时声明和实例化类的方法。它们与任何其他类一样,只是没有名称。无论何时声明一个内部类,无论它是否为匿名类,编译器都会为该类创建一个内部类。就像这里发生的一样,编译器创建了一个内部类,如下所示
static class TestAnonymousInner$1 extends Person
{
TestAnonymousInner$1(){}
void eat()
{
System.out.println("nice fruits");
}
}
您可以看到,这与任何其他本地类一样。但是由于
Person
是一个抽象的类,如果不进行扩展,它就不能被实例化。这就是为什么编译器创建的内部类的类型是扩展Person
,我想您应该从搜索匿名内部类开始,如果您遇到问题,请返回。这可能会有帮助。实际上我只是从那里来的…我还是不明白。。当我已经将TestAnyMousInner作为我的内部类名时,编译器是如何给出名称的?所以在匿名内部类中,我必须在创建外部类的实例时定义所有抽象方法?不,不是外部类。它只是您想要创建实例的任何类。在本例中,它是Person
@HarishAmarnath