论坛首页 Java企业应用论坛

期待好久的JDK8新特性:接口可以有default的实现方法

浏览 4416 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2015-05-26   最后修改:2015-05-26
    多年来在做业务实体建模的时候,经常会碰到这样的场景:基类为Entity,有多个具体的实体类AEntity,BEntity,CEntity等,然后这些实体可能具有编号排序和拼音码功能。现在来做实现:定义NoSortable接口和Pinyinable接口,另外为了代码的复用,再提供抽象类NoSortEntity和PinyinEntity,继承自Entity,实现默认的编号比较和拼音码处理功能,供具体的实体类继承。
    现在问题来了:如果CEntity同时具有这2个功能,因为Java的单继承限制,就没办法复用NoSortEntity和PinyinEntity的代码,只能是另外写一个NoSortPinyinEntity抽象类来供CEntity继承,提供这2个功能的默认实现。可以想像,如果类似的功能接口很多的话,那就会形成类爆炸的情况,会有很多组合功能的中间抽象类,这样就违反了使用抽象类复用代码的初衷(除非这些抽象类完全只用一棵继承树,而这显然是糟糕的设计),而且这些组合的抽象类的命名也是个麻烦的问题。有C++编程经验的同事看到这里就知道,这种场景用多继承很容易就解决掉了。基于此,多年来在技术交流讨论中,我一直对Java的单继承深深诟病,并断定以后的JDK一定会支持多继承,因为类似的这种场景在业务建模中是很常见的。不能因为多继承的滥用会容易导致一些问题,就在语言级别抛弃多继承,这是典型的削足适履。
    这个问题一直困扰了我很久,直到最近偶然一次,在eclipse里看到Collection和List接口的源码里有这样的代码:

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}


    晕了,接口不是不能有实现的代码么。。。上网查了一下,才了解到这是JDK8的新特性:接口可以有default的实现方法,子类可以直接用接口的默认实现。因为Java类可以继承多个接口,所以这其实就是多继承的一种变相的实现嘛(验证了我之前的断言)。这样多好!这很容易就解决掉了上面的那种需要复杂组合的场景。而且这样还有一个好处:升级了新的JRE或依赖包后,旧的业务代码不一定需要修改,因为接口提供了默认的实现,而在JDK7及之前的时代,这种情况必须修改业务代码,实现接口新增的方法,否则编译都过不了,运行也会报错。
    当然,这样并不能避免多继承可能导致的一个方法冲突的问题:如果继承的多个接口都有相同方法的默认实现,那实际调用的是哪一个呢?JDK8的规则是:哪个都不用,子类要另外写一个实现。我觉得这样虽然有点死板,但也是可以接受的,毕竟方法冲突很少会发生,而且通过一些编码规范或者开发环境的支持,是可以杜绝冲突的。
    顺便过了一下JDK8的新特性,除了接口的default方法,还有集合类初始化增强及批量数据操作增强,Lambda表达式,方法引用(应该类似C++提供回调的函数指针)等,慢慢研究后在团队中推广吧。。。。。。。。。。
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics