java8之默认方法

默认方法是啥

默认方法是由default修饰符修饰,并像类中声明的其他方法一样包含方法体。是Java8中新添加的能力。

默认方法能干啥

可选方法

默认方法的主要应用场景在定义API上,可以避免临时往接口里面加方法导致的尴尬。

举一个身边的例子。比如Android升级的时候往接口里加了个方法,但是方法又不常用,升级的时候我们就不得不实现一下这个方法然后加一个空实现或者抛出一个未支持异常。但是现在有了默认方法,这种场景下Android就可以写一个默认方法,不用我们非得实现一个我们不会去使用的接口方法了。

总之,对于那些不是一定要实现的接口方法,我们可以避免在实现的时候刻意留白的情况出现。

函数式接口

之前讲过,函数式接口是只包含一个抽象方法的接口。这句话在以前不需要过多考虑,但是现在有了默认方法就不一样了。因为默认方法不是抽象方法,所以我们多些几个默认方法是不影响的。实际上现在的函数式接口Predicate、Function以及Comparator确实也引入了默认方法。

行为的多继承

当年学Java的时候,学到继承的位置需要特别注意的一点是Java不像C++一样支持行为多继承。现在不一样了,有了默认方法大家可以在接口里写实现了,这时实现多个接口我们自然就拥有它们各个接口的能力了。

利用这一点,我们可以把能够解决独立能力的通用代码抽成接口,并把需要的能力用默认方法实现。当我们想要用的这些能力的时候实现一下接口就可以了。这种方式与模版设计模式类似。

默认方法存在啥问题

方法名冲突

在默认方法之前如果实现两个有重名的方法的接口,对于重名的接口方法实现成一个就好了。但是现在有了默认方法,如果两个接口中有同名的默认方法,那么在同时实现这两个接口的时候会选择使用哪一个方法呢?这种情况有极低可能会出现,但还是要有规则来处理这种问题。

解决问题的三条规则

  1. 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
  2. 如果无法依据第一条进行判断,那么子接口的优先级最高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
  3. 最后,如果还是无法判断,继承了多个接口的类必须通过显示覆盖和调用期望的方法,显示的选择使用哪一个默认方法的实现。

以上三条规则就能够处理所有冲突的问题,下面举个例子说明一下。

示例一
public interface A {
    default void hello() {
        System.out.println("A");
    };
}

public interface B extends A{
    @Override
    default void hello() {
        System.out.println("B");
    };
}

public class D implements A {
    //未实现hello()
}

public class C extends D implements B, A {
    public static void main(String... args) {
        new C().hello();
    }
}

看上面代码,首先根据规则1,类中声明的方法具有最高权限,但是类D中并未实现默认方法hello。这里如果类D实现了hello,那么他就拥有最高优先级了。接下来看规则2,看谁更加具体,因为B继承了A,那么B更加具体,所以打印出来的是"B"。

示例二

先上代码

public interface A {
    default void hello() {
        System.out.println("A");
    };
}

public interface B {
    default void hello() {
        System.out.println("B");
    };
}
public class C implements B, A {
    public static void main(String... args) {
        new C().hello();
    }
}

这种情况会打印什么呢?答案是会抛出编译错误,因为无法判断出谁更具体一些。这个时候就需要显式调用了。

具体的方法是覆盖实现该方法,并且在方法中显式调用。关于显示调用,Java8中引入的新语法X.super.m(...),其中X是你希望调用的m方法所在的父接口。例如,上面的问题就可以像下面代码这样显示调用。

public class C implements B,A {

    public static void main(String... args) {
        new C().hello();
    }
    
    @Override
    public void hello() {
        A.super.hello();
    }
}

最后

多说两句

虽然现在接口里也可以写实现了,抽象类和接口还是有区别的。首先类只能继承一个抽象类,但可以实现多个接口。其次抽象类可以定义变量,接口不行。

个人认为默认函数最大的意义还是便于API的编写,避免接口必须实现的痛苦。

最最后

打完,收工!不要问我为什么跳过了Stream,因为功能很强大,写起来太费劲了。欢迎大家讨论提出意见~~

欢迎关注【Funny新青年】微信公众号

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352