繁体   English   中英

这个Java代码如何实例化一个抽象类?

[英]How does this Java code instantiate an abstract class?

我正在更改我们的Java类,我注意到以下代码行:

OurClass<OurInterface1> ourClass = new OurClass<OurInterface1>() {};

OurClass一行感到奇怪的是, OurClass是一个抽象类 - 这里是OurClass的定义:

public abstract class OurClass<T extends OurInterface1> implements OurInterface2<T>

当我删除行末尾的{}时,Eclipse告诉我Cannot instantiate the type OurClass<OurInterface1> ,但当我把{}放回去时,一切正常。

{}如何允许您实例化一个抽象类?

添加{}引入了匿名内部类的语法。

匿名类表达式包含以下内容:

  • 新的运营商

  • 要实现的接口的名称或要扩展的类。 在此示例中,匿名类正在实现接口HelloWorld。

  • 括号,包含构造函数的参数,就像普通的类实例创建表达式一样。 注意:实现接口时,没有构造函数,因此您使用一对空括号,如本例所示。

  • 身体,是一个类声明体。 更具体地说,在正文中,方法声明是允许的,但语句不是。

您正在声明一个匿名内部类,它是OurClass子类。 这个类的主体是空的: {} 这个匿名内部类不是abstract ,因此您可以实例化它。

当你删除{} ,编译器认为你直接实例化了一个abstractOurClass ,所以它不允许它。

调用new运算符后的块( new OurClass<OurInterface1>() {} )实际上是创建一个扩展OutClass的匿名类的实例。

由于这个类不再是abstract ,因此实例化它没有问题。

实际上,当您实例化接口或可扩展类时,您可以实时扩展和覆盖方法。 这称为匿名内部类。

你在你的例子中所做的是创建一个匿名的内部类,但它没有任何效果,因为你没有覆盖任何东西。 您可以将重写的方法放在那些大括号{}

OurClass<OurInterface1> ourClass = new OurClass<OurInterface1>() {}; 

匿名内部类的常用应用是在Runnable接口上,该接口定义了一个void run()方法。 您可以隐式实例化实现Runnable的对象并动态覆盖run()

Runnable someTask = new Runnable() { 
    @Override
    public void run() { 
        System.out.println("Running a task!");
    }
};

许多开发人员都不喜欢匿名内部类,因为它们非常冗长。 幸运的是,在Java 8中,您可以使用lambda表达式来替换实现单个方法的大多数匿名内部类。 编译器基本上为您推断了匿名内部类,允许您更简洁地编写代码。

Runnable someTask = () -> System.out.println("Running a task!");

如果不在类中实现抽象函数,则无法实例化抽象类。 这通常通过使用已实现的类实现抽象类来完成。 请参阅: https//docs.oracle.com/javase/tutorial/java/IandI/abstract.html

在您的情况下,实例化后使用的{}允许您在抽象类中实现任何抽象函数。

例如,

考虑

public abstract class  DummyClass {
 abstract void test() ; 

}

是具有抽象函数的抽象类。

该课程可以通过以下方式发起:

DummyClass d = new DummyClass(){
       void test(){
             //test() implementation here 
        }
    } ;

希望这可以帮助! :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM