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

时间:2017-04-19 09:52:58

标签: 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 fruits");
            } // what happens here?
        };
        p.eat();
    }
}  

3 个答案:

答案 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)

Personabstract所以你无法实例化它;但是通过在实例化期间为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");  
    }  
} 

你可以看到这就像任何其他本地类一样。但由于Personabstract类,因此无法在不扩展的情况下进行实例化。这就是为什么编译器创建内部类的类型为extends Person