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

4

我正在修改我们的Java类,发现以下代码行:

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

我觉得这行代码有点奇怪,因为OurClass是一个抽象类 - 这是OurClass的定义:
public abstract class OurClass<T extends OurInterface1> implements OurInterface2<T>

当我在行末删除 {} 时,Eclipse 告诉我 Cannot instantiate the type OurClass<OurInterface1>,但是当我把 {} 放回去,一切都好了。 {} 如何让你实例化一个抽象类?
4个回答

7
添加{}引入了匿名内部类的语法。
匿名类表达式包括以下内容:
- new操作符 - 要实现的接口名称或要扩展的类名称。在此示例中,匿名类正在实现HelloWorld接口。 - 括号,其中包含构造函数的参数,就像普通的类实例创建表达式一样。注意:当你实现一个接口时,没有构造函数,所以你使用一个空的括号,就像这个例子一样。 - 一个主体,它是一个类声明主体。更具体地说,在主体中,方法声明是允许的,但语句不允许。
你正在声明一个匿名内部类,它是OurClass的子类。这个类的主体是空的:{}。这个匿名内部类不是abstract,所以你可以实例化它。
当您删除 {} 时,编译器会认为您正在直接实例化一个抽象类 OurClass,因此会禁止它。

2

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

在你的示例中,你创建了一个匿名内部类,但它没有任何效果,因为你没有覆盖任何内容。你可以在那些花括号 {} 中放置覆盖后的方法。

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!");

1
在调用new操作符后的代码块(new OurClass<OurInterface1>() {})实际上是创建了一个匿名类的实例,该类继承自OutClass
由于这个类不再是抽象的,所以可以实例化它。

0

在没有实现抽象类中的抽象函数的情况下,您无法实例化抽象类。通常通过使用已实现类来实例化抽象类来完成此操作。 参考: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 
        }
    } ;

希望这有所帮助!:)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接