Java 中默认关键字的用途是什么?

2022-08-31 07:52:48

Java中的接口类似于类,但接口的主体只能包含抽象方法和字段(常量)。final

最近,我看到一个问题,看起来像这样

interface AnInterface {
    public default void myMethod() {
        System.out.println("D");
    }
}

根据接口定义,只允许使用抽象方法。为什么它允许我编译上面的代码?关键字是什么?default

另一方面,当我试图编写下面的代码时,它说modifier default not allowed here

default class MyClass{

}

而不是

class MyClass {

}

谁能告诉我关键字的目的?是否只允许在接口内使用?它与(无访问修饰符)有何不同?defaultdefault


答案 1

这是Java 8中的一个新功能,它允许提供实现。在 Java 8 JLS-13.5.6 中进行了描述。读取(部分)的接口方法声明interface

添加方法或将方法从 更改为 不会破坏与预先存在的二进制文件的兼容性,但如果预先存在的二进制文件尝试调用该方法,则可能会导致冲突。如果限定类型 、 是两个接口的子类型,并且 ,其中 两者都声明了一个具有相同签名和结果的方法,并且既不是另一个接口的子接口,也不会是另一个接口的子接口,则会发生此错误。defaultabstractdefaultIncompatibleClassChangeErrorTIJIJdefaultIJ

JDK 8 中的新增功能说(部分)

默认方法允许将新功能添加到库的接口中,并确保与为这些接口的旧版本编写的代码的二进制兼容性。


答案 2

默认方法被添加到 Java 8 中,主要是为了支持 lambda 表达式。设计人员(在我看来,巧妙地)决定制作lambdas语法来创建接口的匿名实现。但是,假设lambda只能实现单个方法,它们将仅限于具有单个方法的接口,这将是一个非常严格的限制。相反,添加了默认方法以允许使用更复杂的接口。

如果你需要一些令人信服的由于lambdas而引入的声明,请注意,Mark Reinhold在2009年提出的Lambda项目的稻草人提案提到“扩展方法”是添加以支持lambda的强制性功能。default

下面是一个演示该概念的示例:

interface Operator {
    int operate(int n);
    default int inverse(int n) {
        return -operate(n);
    }
}

public int applyInverse(int n, Operator operator) {
    return operator.inverse(n);
}

applyInverse(3, n -> n * n + 7);

我意识到非常人为,但应该说明如何支持lambdas。因为 是默认值,如果需要,它可以很容易地被实现类覆盖。defaultinverse