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

Java中默认关键字的用途是什么?,java,interface,java-8,default,Java,Interface,Java 8,Default,Java中的接口类似于类,但它是类的主体 界面只能包含抽象方法和最终字段 (常数) 最近,我看到一个问题,看起来像这样 interface AnInterface { public default void myMethod() { System.out.println("D"); } } 根据接口定义,只允许使用抽象方法。为什么它允许我编译上面的代码?默认的关键字是什么 另一方面,当我试图写下面的代码时,它说这里不允许修改器default default cl

Java中的接口类似于类,但它是类的主体 界面只能包含抽象方法
最终
字段 (常数)

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

interface AnInterface {
    public default void myMethod() {
        System.out.println("D");
    }
}
根据接口定义,只允许使用抽象方法。为什么它允许我编译上面的代码?默认的
关键字是什么

另一方面,当我试图写下面的代码时,它说
这里不允许修改器default

default class MyClass{

}
而不是

class MyClass {

}

谁能告诉我
default
关键字的用途吗?是否只允许在接口内部使用?它与默认值(无访问修饰符)有何不同

这是Java8中的一个新特性,它允许
接口提供一个实现。在Java 8中描述,其中读取(部分)

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

说(部分)

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


默认方法允许您向应用程序的界面添加新功能。它还可用于进行多重继承。
除了默认方法外,还可以在接口中定义静态方法。这使您更容易组织助手方法

在Java8中引入了一个称为默认方法的新概念。默认方法是那些具有一些默认实现并有助于在不破坏现有代码的情况下改进接口的方法。让我们看一个例子:

 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实现将默认方法添加到Java8中,主要是为了支持lambda表达式。设计者(在我看来很聪明)决定使用lambdas语法来创建匿名接口实现。但鉴于lambda只能实现一个方法,它们将被限制为具有一个方法的接口,这将是一个非常严格的限制。相反,添加了默认方法以允许使用更复杂的接口

如果您需要一些令人信服的说法,即由于lambdas而引入了
default
,请注意,Mark Reinhold在2009年提出的Lambda项目中提到了“扩展方法”作为支持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
是一个默认值,如果需要,它可以很容易地被实现类覆盖。

新的Java8特性()允许接口在标记有
default
关键字时提供实现

例如:

interface Test {
    default double getAvg(int avg) {
        return avg;
    }
}
class Tester implements Test{
 //compiles just fine
}
接口测试使用default关键字,该关键字允许接口提供方法的默认实现,而无需在使用接口的类中实现这些方法

向后兼容性: 假设您的接口是由数百个类实现的,修改该接口将迫使所有用户实现新添加的方法,即使对于实现您接口的许多其他类来说这不是必需的

事实与限制:

1-只能在接口中声明,而不能在类或 抽象类

2-必须提供一个机构


3-与界面中使用的其他常规方法不同,它不被认为是公开的或抽象的。

中有一个很好的解释,部分解释如下:

考虑一个涉及计算机控制汽车制造商的例子,他们发布了行业标准接口,描述了可以调用哪些方法来操作他们的汽车。如果这些计算机控制的汽车制造商在他们的汽车上增加了新的功能,比如飞行,会怎么样?这些制造商需要指定新的方法,以使其他公司(如电子制导仪器制造商)能够将其软件适应飞行汽车。这些汽车制造商将在哪里宣布这些新的飞行相关方法?如果他们将它们添加到原始接口中,那么实现这些接口的程序员将不得不重写它们的实现。如果将它们添加为静态方法,那么程序员会将它们视为实用方法,而不是基本的核心方法


默认方法使您能够向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码的二进制兼容性。

其他答案中忽略了它在注释中的作用。早在Java1.5中,
default
关键字就作为注释字段的一种方法出现了

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
    String value() default "AMD";
}
随着Java8的引入,它的使用被重载,从而允许在接口中定义默认方法

还有一点被忽略了:声明
默认类MyClass{}
无效的原因是由于以下方式。该语言中没有允许该关键字出现在此处的规定。它确实出现了,图格
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();
      }
   }