Java 实例化抽象类时发生了什么?什么是匿名内部类?

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

实例化类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();
    }
}  

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