为了账号安全,请及时绑定邮箱和手机立即绑定

java8之后的接口

标签:
Java

java8引入了stream。支持集合对象转化成为stream。集合的接口上增加了一个方法。

    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

我们可以看到集合的接口上。增加了一个实现。
这个就是java8带来的一个特性。接口支持了default关键字。
这样带来了什么好处呢?

default的好处

我们尝试如果没有default,我们要如何实现。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

这个是arraylist的实现。我们看到如果想给所有的核心类库加。似乎我们只要collection加上接口。然后再AbstractList实现就可以了,这样核心类库的list就可以了。同理还有map

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

如果是第三方的实现呢,例如自己为了区别,直接实现了List或者直接实现了collection。这样的代码最可怕了,需要我们一个一个加上方法,才能编译过去,而且实现的内容大同小异。
第三方实现的时候,可能没有核心类库这么强大,没有做中间的抽象类做区分,实现起来可能就极其复杂。
最麻烦的是,原来6写出来的代码,编译出的class文件无法直接跑在8上。严重影响升级版本的。
直接在接口上加一个实现,直接避免了这个问题,用户的code基本是不要改变的。

default的坏处

上面从兼容性,开发等角度,讲了default如果没有的话,可能带来的问题。
在8之前,接口和抽象类是有明确的分工的。

  • 接口是用来定义规范。
  • 抽象类是用来复用代码。

根据这样的设计规则,我们设计code会更有章法。抽象类一出,大家的关注点都在protected方法和final方法。这个一般意味着,重点聚焦在继承和抽象层面的规范化。
按照这个角度,看stream方法应该是设计在抽象类上的。并且设计成final。spliterator是一个protected方法,希望子类继承的时候,各自做各自的实现。
在接口中可以加方法实现,这个会导致原来的潜在约定失效。大家得仔细想想这个实现具体来自哪里。

所以我们正常开发依旧会遵循接口和抽象类的区别,但是在改造系统上,我们会利用default关键字来让改造更快。

菱形继承问题

这个多层继承本来是cpp的多继承问题,现在java的接口也同时有了这个问题。原来的接口是没有实现的。所以最终只有一份实现。但是现在不一样了。

interface FA {
    default void say() {
        System.out.println("FA");
    }

    ;
}
interface FA1 extends FA{
    
}

这种继承是没有问题的。


interface FA {
    default void say() {
        System.out.println("FA");
    }

    ;
}


interface FB {
    default void say() {
        System.out.println("FB");
    }
}

interface FC extends FA, FB {

    @Override
    default void say() {

    }
}

这种情况,编译器会要求你FC实现方法。

interface FA {
    default void say() {
        System.out.println("FA");
    }
}


inerface FB {
    default void say() {
        System.out.println("FB");
    }
}

interface FC extends FA, FB {

    @Override
    default void say() {
        FB.super.say();
    }
}

可以再实现中,主动的指定实现的到底是来自谁的方法。
这里建议多层和菱形的情况下,虽然有默认规则,但还是最好手动指定一下实现的情况。因为默认的情况,依赖继承顺序。如果有一个稍加改动,默认的值就变了。但是编译时还发现不了。所以最好都是明确指定,之后就不可动了,后面谁修改的时候,需要手动确认一次。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.6万
获赞与收藏
380

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消