【问题标题】:What is happening while instantiating an abstract class? What is an anonymous inner class?实例化抽象类时发生了什么?什么是匿名内部类?
【发布时间】:2017-04-19 09:52:58
【问题描述】:

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

【问题讨论】:

标签: java anonymous-inner-class


【解决方案1】:

匿名类实际上只是语法糖。

由于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。内部类被赋予了一个非常特殊的名称(我不记得是什么),因此普通代码无法访问它。

附:在 Java 8 中,引入了 lambda。它们又是只有一种方法的接口的语法糖。但这不适用于抽象类。

【讨论】:

  • 所以在匿名内部类中我必须在创建外部类的实例时定义所有抽象方法?
  • 不,不是外部类。它只是您想要创建实例的任何类。在这种情况下,它是Person@HarishAmarnath
【解决方案2】:

Personabstract 所以你不能实例化它;但是通过在实例化过程中注入abstract 方法的实现,Person 变为“可实例化”;最后调用eat(),结果将是:eat() => nice fruits

【讨论】:

    【解决方案3】:

    实际上匿名内部类是同时声明实例化一个类的方式。除了没有名称之外,它们与任何其他类一样。每当您声明一个 Inner class 时,无论它是否是 Anonymous,Compiler 都会为该类创建一个内部类。就像这里发生的一样,编译器创建了一个内部类,如下所示

    static class TestAnonymousInner$1 extends Person  
    {  
       TestAnonymousInner$1(){}  
       void eat()  
        {  
            System.out.println("nice fruits");  
        }  
    } 
    

    您可以看到这就像任何其他本地课程一样。但是由于Person 是一个abstract 类,它不能在没有扩展的情况下被实例化。这就是为什么编译器创建的内部类的类型是extends Person

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-12
      • 2019-09-07
      • 1970-01-01
      • 2013-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多