我们都知道在Java语言的接口中只能定义方法名,而不能包含方法的具体实现代码。接口中定义的方法必须在接口的非抽象子类中实现。下面就是关于接口的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface SimpleInterface {
  public void doSomeWork();
}
 
class SimpleInterfaceImpl implements SimpleInterface{
  @Override
  public void doSomeWork() {
    System.out.println("Do Some Work implementation in the class");
  }
 
  public static void main(String[] args) {
    SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
    simpObj.doSomeWork();
  }
}

那么,如果我们在SimpleInterface里面添加一个新方法,会怎样呢?

1
2
3
4
public interface SimpleInterface {
  public void doSomeWork();
  public void doSomeOtherWork();
}

如果我们尝试编译上面的这段代码,会得到如下结果:

1
2
3
4
5
6
$javac .\SimpleInterface.java
.\SimpleInterface.java:18: error: SimpleInterfaceImpl is not abstract and does not
override abstract method doSomeOtherWork() in SimpleInterface
class SimpleInterfaceImpl implements SimpleInterface{
^
1 error

因为接口有这个语法限制,所以要直接改变/扩展接口内的方法变得非常困难。我们在尝试强化Java 8 Collections API,让其支持lambda表达式的时候,就面临了这样的挑战。为了克服这个困难,Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。

Default方法是指,在接口内部包含了一些默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制),从而使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。接下来,让我们看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface SimpleInterface {
  public void doSomeWork();
 
  //A default method in the interface created using "default" keyword
  //使用default关键字创在interface中直接创建一个default方法,该方法包含了具体的实现代码
  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.
   * 在SimpleInterfaceImpl里,不需要再去实现接口中定义的doSomeOtherWork方法
   */
 
  public static void main(String[] args) {
    SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
    simpObj.doSomeWork();
    simpObj.doSomeOtherWork();
  }
}

该程序的输出是:

1
2
Do Some Work implementation in the class
DoSomeOtherWork implementation in the interface

以上是对default方法的一个非常简要的介绍。如果有兴趣的话,还可以通过看这篇文档,来获取更深层次的理解。

更新:

现在大家问得比较多的一个问题是:如果一个类实现了两个接口(可以看做是“多继承”),这两个接口又同时都包含了一个名字相同的default方法,那么会发生什么情况? 在这样的情况下,编译器会报错。让我用例子来解释一下:

1
2
3
4
5
6
7
8
9
10
11
public interface InterfaceWithDefaultMethod {
  public void someMethod();
  default public void someOtherMethod(){
    System.out.println("Default method implementation in the interface");
  }
}
public interface InterfaceWithAnotherDefMethod {
  default public void someOtherMethod(){
    System.out.println("Default method implementation in the interface");
  }
}

然后我们定义一个类,同时实现以上两个接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DefaultMethodSample implements
  InterfaceWithDefaultMethod, InterfaceWithAnotherDefMethod{
 
  @Override
  public void someMethod(){
    System.out.println("Some method implementation in the class");
  }
  public static void main(String[] args) {
    DefaultMethodSample def1 = new DefaultMethodSample();
    def1.someMethod();
    def1.someOtherMethod();
  
}

如果编译以上的代码,会得到一个编译器错误,如下所示。因为编译器不知道应该在两个同名的default方法中选择哪一个,因此产生了二义性。

原文链接: blog.sanaulla.info 翻译: ImportNew.com黄小非
译文链接: http://www.importnew.com/7302.html
转载请保留原文出处、译者和译文链接。]

Java 8新特性——default方法(defender方法)介绍的更多相关文章

  1. Java 8 新特性--Lambda表达式作为方法参数

    Lambda表达式的使用场景: 当方法的参数是一个函数式接口时,可以使用Lambda表达式进行简化—— 首先,前提是Runnable接口是一个函数式接口,经过查看源码得知,确实如此: 将Runnabl ...

  2. Java 8 新特性-Stream更优雅的处理集合入门

    Java 8 新特性之--Stream 一. 简单介绍 Stream是Java 8提出了的一种新的对集合对象功能的增强.它集合Lambda表达式,对集合提供了一些非常便利,高效的操作,使得代码具有非常 ...

  3. Java 8新特性-4 方法引用

    对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容! Java 8的方法引用定义了四种格式: 引用静态方法     ClassName :: staticMetho ...

  4. C# 7.0 新特性2: 本地方法

    本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...

  5. Java8新特性之二:方法引用

    上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...

  6. C#10新特性-lambda 表达式和方法组的改进

    C# 10 中对Lambda的语法和类型进行了多项改进: 1. Lambda自然类型 Lambda 表达式现在有时具有"自然"类型. 这意味着编译器通常可以推断出 lambda 表 ...

  7. Java 8新特性终极指南

    目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展 ...

  8. Java 8 新特性终极版

    声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己 ...

  9. Java 8新特性前瞻

    快端午小长假了,要上线的项目差不多完结了,终于有时间可以坐下来写篇博客了. 这是篇对我看到的java 8新特性的一些总结,也是自己学习过程的总结. 几乎可以说java 8是目前为止,自2004年jav ...

随机推荐

  1. IOS中把字符串加密/IOS中怎么样MD5加密/IOS中NSString分类的实现

    看完过后,你会学到: 1学习IOS开发中的分类实现, 2以及类方法的书写, 3以及字符串的MD5加密/解密. ---------------------------wolfhous---------- ...

  2. Unity3D事件函数的执行顺序 - 包含渲染等模块的完整版,中英文对照

    原文地址: http://www.cnblogs.com/ysdyaoguai/p/3746828.html In Unity scripting, there are a number of eve ...

  3. Retrofit源码设计模式解析(上)

    Retrofit通过注解的方法标记HTTP请求参数,支持常用HTTP方法,统一返回值解析,支持异步/同步的请求方式,将HTTP请求对象化,参数化.真正执行网络访问的是Okhttp,Okhttp支持HT ...

  4. java网络---查找Internet

    连接到Internet的设备称为节点,计算机节点称为host. 为了区别每一台连接互联网的计算机,就有了Internet Protocol地址的概念. IPV4 & IPV6 我们以前默认的是 ...

  5. office2010安装报错

    有没有童鞋,在第一次安装office 2010的时候,中途不管是何原因导致中断或者未安装成功的 然后从第二次开始就一直安装报错??? 哈哈,我最近就遇到了 其他很简单,网上有很多方法,也有很多步骤,包 ...

  6. CentOS 6.4安装配置LAMP服务器(Apache+PHP5+MySQL)

    这篇文章主要介绍了CentOS 6.4安装配置LAMP服务器(Apache+PHP5+MySQL)的方法,需要的朋友可以参考下 文章写的不错,很详细:IDO转载自网络: 准备篇: 1.配置防火墙,开启 ...

  7. Jmeter组件执行顺序与作用域

    一.Jmeter重要组件: 1)配置元件---Config Element: 用于初始化默认值和变量,以便后续采样器使用.配置元件大其作用域的初始阶段处理,配置元件仅对其所在的测试树分支有效,如,在同 ...

  8. (ios)ARC常用设置,部分文件编译设置ARC

    1设置 整个项目是否支持ARC 选择No 不支持 YES 支持 2 设置部分文件是否支持ARC. 支持ARC的Flags -fobjc-arc   不支持的Flags -fno-objc-arc

  9. 斐波那契数列 递归 尾递归 递推 C++实现

    ==================================声明================================== 本文原创,转载请注明作者和出处,并保证文章的完整性(包括本 ...

  10. sql 把特定数据排在最前面

    感谢www.baidu.com/p/dongfanghong_1 sql大神,简单的语法运用起来简直活了. 第一法] select * from table where name='D' UNION ...