• Java 8新特性——default方法(defender方法)介绍


    我们都知道在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
    转载请保留原文出处、译者和译文链接。]

  • 相关阅读:
    NETCore EF 数据库连接正确nuget和MySql错误异常
    JS 对象属性名排序
    NET 在一个数组中查找另一个数组所在起始位置(下标从0开始,未找到返回-1)
    NET 判断是否为回文
    NET/Regex 处理连续空格
    NET 已知excel表格前面26个是a到z,27是aa28是ab,以此类推,N是多少
    Regex 首字母转大写/小写,全大写,全小写
    .NETCore下访问img、js等静态资源404解决办法
    WPF-后台代码使用Behavior
    Socket-服务器端与客户端互相通信
  • 原文地址:https://www.cnblogs.com/flying607/p/5521627.html
Copyright © 2020-2023  润新知