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

How does this Java code instantiate an abstract class?

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

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

我对该行感到奇怪的是 OurClass 是一个抽象 class - 这是 OurClass 的定义:

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

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

{} 如何让您实例化抽象 class?

添加 {} 引入了 anonymous inner class.

的语法

The anonymous class expression consists of the following:

  • The new operator

  • The name of an interface to implement or a class to extend. In this example, the anonymous class is implementing the interface HelloWorld.

  • Parentheses that contain the arguments to a constructor, just like a normal class instance creation expression. Note: When you implement an interface, there is no constructor, so you use an empty pair of parentheses, as in this example.

  • A body, which is a class declaration body. More specifically, in the body, method declarations are allowed but statements are not.

您正在声明一个匿名内部 class 子 class 是 OurClass。 class 的正文是空的:{}。这个匿名内部 class 不是 abstract,所以你可以实例化它。

当您删除 {} 时,编译器认为您是在直接实例化 OurClassabstract class,因此它不允许它。

调用 new 运算符 (new OurClass<OurInterface1>() {}) 之后的代码块实际上是在创建扩展 OutClass 的匿名 class 的实例。

既然这个class不再是abstract,实例化就没有问题了。

如果不在 class 中实现抽象函数,则无法实例化抽象 class。这通常是通过实例化抽象 classes 和实现的 class 来完成的。 参考:https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

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

例如,

考虑

public abstract class  DummyClass {
 abstract void test() ; 

}

是具有抽象功能的抽象class。

class 可以通过以下方式启动:

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

希望对您有所帮助! :)

当您实例化一个接口或可扩展的 class 时,您实际上可以动态地扩展和覆盖方法。这称为匿名内部 class.

您在示例中所做的是创建一个匿名内部 class,但它没有任何效果,因为您没有覆盖任何内容。您可以将覆盖的方法放在那些大括号 {}.

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

匿名内部 class 的一个普遍应用是在 Runnable 接口上,它定义了一个 void run() 方法。您可以隐式实例化一个实现 Runnable 的对象并即时覆盖 run()

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

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

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