传统上,Java程序的接口是将相关方法按照预定组合到一起的方式。实现接口的类必须为接口中定义的方法提供一个实现,或者从父类中集成它的实现。但是,一旦类库的设计者需要更新接口,向接口中加入新的方法时候,这种方式就会出现问题。现存的类为了适应新的接口约定也要进行修改。

  Java 8为了解决这个问题,现在接口支持在生命方法的同时提供实现,Java 8 允许在接口内声明静态方法,Java 8 允许在接口中创建默认方法。默认方法可以指定所有实现类的默认实现。这种模式可以让你平滑的进行接口的优化。

List中的sort方法就是一个静态方法:

    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);
}
}

通过default关键字来在接口中定义默认方法。可以直接调用sort,对列表进行排序:

Arrays.asList(1,2,3,5,54).sort(Comparator.naturalOrder());

Comparator.naturalOrder是一个静态方法,它返回了一个Comparator对象,按照自然序列对其中的元素进行排序

    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}

Collection中的Stream方法也是一个静态方法:

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

Stream是通过StreamSupport调用了一个stream方法,来返回的Stream对象。并且,现在你知道spliterator 是怎么来的了吧,它也是Collection接口的一个默认方法。

默认方法的引用就是为了解决Java API这样的类库演进问题。因为向接口中增加方法会导致所有实现类受害。它们也都要进行更新。默认方法可以让所有实现类自动继承接口的一个默认实现。

定义默认方法

  使用default前缀,并加入方法体即可,比如定义一个sized接口:

public interface Sized {
int size();
default boolean isEmpty(){
return size() == 0;
}
}

所有的实现类,都会自动继承isEmpty的实现。

Java8中的抽象类和抽象接口

  抽象接口是指函数式接口中 包含的方法->如 Predicate中的test。

    一个类只能继承一个抽象类,但是一个类可以实现多个接口。

  一个抽象类可以设置实例变量,接口不能有实例变量。

可选方法

  有时,一个类实现了接口,不过却刻意的将一些方法的实现留白。以Iterator接口为例,Iterator接口定义了hasNext、next还有remove方法。Java 8 之前,由于用户通常不会使用该方法,remove方法常被忽略。因此,实现了Iterator接口的类通常会为remove方法放置一个空的实现,这些都是毫无用处的模板代码。

  采用默认方法之后,你可以为这种类型的方法提供一个默认的实现,这样实体类就无需在自己的实现中显示的提供一个空方法。

interface Iterator<T> { 

    boolean hasNext();
T next();
default void remove() {
throw new UnsupportedOperationException();
}
}

通过这种方式,可以减少很多无效的模板代码。无需再实现remove方法。

行为的多继承

  默认方法之前是无法优雅的实现多继承的,让一个类从多个来源重用代码的能力。因为java的类只能继承单一的类,但是一个类可以实现多个接口。比如ArrayList类的定义:

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

它继承了一个类,实现了4个接口。因此ArrayList实际上是7个类型的直接子类。在某种程度上,我们早就有了多继承。

由于Java 8中的接口也可以提供实现,类可以从多个接口中继承他们的行为。

比如你要实现一个接口,有的类需要可以放大缩小,不需要改变形状。有的类需要改变形状 不需要放大缩小。这时可以将 放大缩小放在一个接口中提供一个实现,放大缩小放在一个接口中,然后在需要的类中 各自实现各自的接口。继承各自的默认实现。不要都放在一个接口中。

解决冲突的规则

  我们知道,一个类只可以继承一个类,但是可以实现多个接口。随着Java 8 带来的默认方法的加入,有可能会出现类或者多个接口中的默认方法出现重复的问题。在这种情况下,

1.类的方法优先级最高,类或父类中声明的方法的优先级高于任何声明的默认方法的优先级。

2.如有无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,如果B实现了A,那么A就更具体。

3.最后,如果还是无法判断,继承了多个接口的类必须通过显示覆盖和调用期望的方法,显示的选择使用哪一个默认方法的实现。

public class C implements B,A{
void hello(){
//显示指定哪个接口中的同名方法
B.supper.hello();
}
}

小结

  1.Java 8中的接口可以通过默认方法和静态方法提供代码的实现。

  2.默认方法的开头以关键字default修饰,方法体与常规类的方法相同。

  3.向发布的接口添加抽象方法不是源码兼容的。

  4.默认方法的出现能帮助库的设计者以后向兼容的方式演进API。

  5.默认方法可以用于创建可选方法和行为的多继承。

  6.当函数名重复时,可以按照优先级进行判断,类和父类实现最高,其他无法确定时,可以显示指定调用哪个。

Java 8 (8) 默认方法的更多相关文章

  1. Java 8 特性 —— 默认方法和静态方法

    Java 8 新增了接口的默认方法.简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法.我们只需在方法名前面加个 default 关键字即可实现默认方法. 为什么要有这个特性?之前的 ...

  2. java 8 接口默认方法

    解决问题:在java8 之前的版本,在修改已有的接口的时候,需要修改实现该接口的实现类. 作用:解决接口的修改与现有的实现不兼容的问题.在不影响原有实现类的结构下修改新的功能方法 案例: 首先定义一个 ...

  3. java8-新特性--(接口的默认方法与静态方法)

    Java 8用默认方法与静态方法这两个新概念来扩展接口的声明. public interface Inte{ void method(); default void defaultMethod(){ ...

  4. Java8 新特性 默认方法

    默认方法为什么出现 默认方法的出现是因为在java8设计的过程中,因为加入了Lamdba表达式,和函数式接口,所以在非常多的接口里面要加入新的方法,但是如果在接口里面直接加入新的方法,那么以前写的所有 ...

  5. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

  6. Java 8函数编程轻松入门(三)默认方法详解(default function)

    default出现的原因 Java 8中对API最大的改变在于集合类,Java在持续演进,但是它一直保持着向后兼容. 在Java 8中为Collection接口增加了stream方法,这意味着所有实现 ...

  7. JAVA 8 默认方法-Default Methods

    什么是默认方法-Default Methods 简单的说,就是可以在接口中定义一个已实现方法,且该接口的实现类不需要实现该方法: 如下示例: interface GreetingService { v ...

  8. [转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...

  9. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

随机推荐

  1. Webstrom打开太慢

    让webstrom将安装包目录屏蔽,settings-搜索file types-在ignore file and folders加入node_modules目录,操作方式如下:

  2. html5 编辑

    在html中想获得矢量图形可以用svg标签.该标签画出的图形全部用代码实现. 可以用在线html编辑工具来进行所见即所得编辑,然后到处源码. 比较好用的工具有http://editor.method. ...

  3. delphi的一些语法知识 以及参数传递问题,按引用方式传递参数,按值方式传递参数

    //delphi中exit,abort,break,continue 的区别 exit: 退出函数体abort: 遇到异常,安静处理,就是不显示不提示break: 退出当前循环体,包括for ,whi ...

  4. 【SSH 基础】浅谈Hibernate--入门篇

    Hibernate是什么 Hibernate是一个轻量级的ORMapping框架 ORMapping原理(Object Relational Mapping)就是把对象里面的数据和数据库里面的数据,依 ...

  5. 【BLE】CC2541之自己定义长短按键

    本篇博文最后改动时间:2017年01月06日,11:06. 一.简单介绍 本文以SimpleBLEPeripheral为例,介绍怎样将普通IO口(P12)自己定义为长短按键,实现按键3S以内松开为短按 ...

  6. S5P4418裸机开发系列教程--源代码下载

    S5P4418裸机系列教程之stdio S5P4418裸机系列教程之shell命令行 S5P4418裸机系列教程之串口回显 S5P4418裸机系列教程之复位測试 S5P4418裸机系列教程之led跑马 ...

  7. IEDA-maven引用本地jia包

    简单说下为啥用maven引用本地jar包:当在pom文件中配置需要引用了jar的坐标,但是maven引用不了(原因未知情况下),这种情况下就需要找开发提供相关依赖的的jar文件打成一个jar包发送过来 ...

  8. [办公自动化]如何让excel图表标签中显示最新值数据

    同事做了一张excel图表,希望最新的数据显示数据标签,其他都不显示.并且当单元格的数据新增加时,这个标签要能自动更新. 这里需要用到公式,获取到这个最新值.在b2输入公式=lookup(9e+307 ...

  9. servlet container:tomcat jetty and undertow

    1 spring boot内嵌容器支持tomcat.jetty和undertow 但是undertow性能最好,详见: https://examples.javacodegeeks.com/enter ...

  10. 蓝桥 ADV-230 算法提高 12-1三角形 【数学公式】

      算法提高 12-1三角形   时间限制:1.0s   内存限制:256.0MB      问题描述 为二维空间中的点设计一个结构体,在此基础上为三角形设计一个结构体.分别设计独立的函数计算三角形的 ...