Java中的接口类似于一个类,但是它的主体 界面可以包括仅抽象方法和
final
字段 (常数)。
最近,我看到了一个问题,看起来像这样
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
根据界面定义,允许使用仅抽象方法。为什么它允许我编译上面的代码?什么是default
关键字?
另一方面,当我尝试编写下面的代码时,它会显示modifier default not allowed here
default class MyClass{
}
而不是
class MyClass {
}
有谁可以告诉我default
关键字的用途?是否只允许在界面内?它与default
(无访问修饰符)有何不同?
答案 0 :(得分:55)
它是Java 8中的一项新功能,允许interface
提供实现。在Java 8 JLS-13.5.6. Interface Method Declarations中描述,它读取(部分)
添加
default
方法或将方法从abstract
更改为default
不会破坏与预先存在的二进制文件的兼容性,但如果是IncompatibleClassChangeError
,则可能会导致T
预先存在的二进制尝试调用该方法。如果限定类型I
是两个接口J
和I
的子类型,其中J
和default
都声明{I
,则会出现此错误1}}具有相同签名和结果的方法,J
和StreamReader
都不是另一个的子接口。
What's New in JDK 8说(部分)
默认方法允许将新功能添加到库的接口,并确保与为这些接口的旧版本编写的代码的二进制兼容性。
答案 1 :(得分:21)
Java 8中添加了默认方法,主要是为了支持lambda表达式。设计师(巧妙地,在我看来)决定使用lambdas语法来创建接口的匿名实现。但鉴于lambdas只能实现单一方法,它们将仅限于使用单一方法的接口,这将是一个非常严格的限制。相反,添加了默认方法以允许使用更复杂的接口。
如果你需要一些说服default
因lambdas而引入的说法,请注意Mark Reinhold在2009年提出的Lambal项目straw man proposal,提及'扩展方法&# 39;作为必须添加以支持lambdas的功能。
这是一个展示这个概念的例子:
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);
非常做作我意识到但应该说明default
如何支持lambdas。由于inverse
是默认值,因此如果需要,可以通过实现类轻松覆盖。
答案 2 :(得分:11)
Java 8中引入了一种称为默认方法的新概念。默认方法是那些具有一些默认实现的方法,有助于在不破坏现有代码的情况下改进接口。让我们看一个例子:
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface{
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
,输出为:
在课堂上做一些工作实施 接口中的DoSomeOtherWork实现
答案 3 :(得分:8)
其他答案中忽略的一点是它在注释中的作用。早在Java 1.5之后,import React, { Component } from 'react';
import TweenMax, {Power4} from 'gsap/src/uncompressed/TweenMax';
import EasePack from 'gsap/src/uncompressed/easing/EasePack';
import TimelineMax from 'gsap/src/uncompressed/TimelineMax';
关键字就作为provide a default value注释字段的一种方式。
default
使用重载,引入了Java 8,允许在接口中定义默认方法。
其他被忽略的事情:声明@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
String value() default "AMD";
}
无效的原因是由于classes are declared at all的方式。语言中没有允许该关键字出现在那里的规定。不过, 会出现在interface method declarations。
答案 4 :(得分:2)
新的 Java 8 功能(Default Methods)允许界面在标有default
关键字时提供实施。
例如:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test使用default关键字,该关键字允许接口提供方法的默认实现,而无需在使用该接口的类中实现这些方法。
向后兼容性: 想象一下,您的接口是由数百个类实现的,修改该接口将强制所有用户实现新添加的方法,即使它对于实现您的接口的许多其他类不是必需的。
事实&限制:
1-May只能在界面内声明,而不是在类或 抽象类。
2 - 必须提供身体
3 - 不假设它是公共的或抽象的,就像接口中使用的其他常规方法一样。
答案 5 :(得分:1)
默认方法使您可以向应用的界面添加新功能。它还可用于具有多重继承。 除了默认方法,您还可以在接口中定义静态方法。这使您更容易组织帮助方法
答案 6 :(得分:1)
The Java™ Tutorials中有一个非常好的解释,部分解释如下:
考虑一个涉及计算机控制汽车制造商的例子,他们发布行业标准接口,描述可以调用哪些方法来操作他们的汽车。如果那些计算机控制的汽车制造商为他们的汽车添加新的功能,例如飞行,该怎么办?这些制造商需要指定新方法,以使其他公司(如电子制导仪器制造商)能够使其软件适应飞行汽车。这些汽车制造商将在哪些地方宣布这些与航班相关的新方法?如果他们将它们添加到原始接口,那么实现这些接口的程序员将不得不重写他们的实现。如果他们将它们作为静态方法添加,那么程序员会将它们视为实用方法,而不是必要的核心方法。
默认方法使您能够向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码具有二进制兼容性。
答案 7 :(得分:0)
界面中的默认方法使我们能够添加新功能而不会破坏旧代码。
在Java 8之前,如果将新方法添加到接口,则该接口的所有实现类都必须重写该新方法,即使它们没有使用新功能。
对于Java 8,我们可以在方法实现之前使用default
关键字为新方法添加默认实现。
即使使用匿名类或函数接口,如果我们看到某些代码是可重用的并且我们不想在代码中的每个地方定义相同的逻辑,我们可以编写这些代码的默认实现并重用它们。
示例
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}