Java 8 之前,接口里面只能写抽象方法,不能写实现方法

Java 8 开始是可以有方法实现的,可以在接口中添加默认方法和静态方法

默认方法用 default 修饰,只能用在接口中,静态方法用 static 修饰,并且接口中的默认方法、静态方法可以同时有多个。

为什么要用接口默认方法

举一个很现实的例子:

我们的接口老早就写好了,后面因为各种业务问题,避免不了要修改接口。

在 Java 8 之前,比如要在一个接口中添加一个抽象方法,那所有的接口实现类都要去实现这个方法,不然就会编译错误,

而某些实现类根本就不需要实现这个方法也被迫要写一个空实现,改动会非常大。

所以,接口默认方法就是为了解决这个问题,只要在一个接口添加了一个默认方法,所有的实现类就自动继承,不需要改动任何实现类,也不会影响业务;

另外,接口默认方法可以被接口实现类重写。

为什么要有接口静态方法?

接口静态方法和默认方法类似,只是接口静态方法不可以被接口实现类重写。

接口静态方法只可以直接通过静态方法所在的 接口名.静态方法名 来调用。

接口默认方法多继承冲突问题

因为接口默认方法可以被继承并重写,如果继承的多个接口都存在相同的默认方法,那就存在冲突问题。

冲突一

interface People {
default void eat() {
System.out.println("人吃饭。");
}
} interface Man {
default void eat() {
System.out.println("男人吃饭。");
}
} //Boy 同时继承了 People 和 Man,此时在 IDEA 编辑器中就会报错
interface Boy extends People, Man { } //这就是接口多继承带来的冲突问题,Boy 不知道该继承谁的,
//这显然也是个问题,IDEA 也会提示,需要重写这个方法才能解决问题:
interface Boy extends People, Man { @Override
default void eat() {
People.super.eat(); //在方法里面还能直接调用指定父接口的默认方法
Man.super.eat(); //在方法里面还能直接调用指定父接口的默认方法
System.out.println("男孩吃饭。");
}
}

用实现类测试一下

class Student implements Boy {
public static void main(String[] args) {
Student student = new Student();
student.eat();
}
} //result
//人吃饭。
//男人吃饭。
//男孩吃饭。

冲突二

我们再换一种写法,把 Man 继承 People,然后 Man 重写 People 中的默认方法

此时,编辑器不报错了,而 People 的默认方法置灰了,提示没有被用到。

再运行一下上面的示例,输出:

interface People {
default void eat() {
System.out.println("人吃饭。");
}
} interface Man extends People{
default void eat() {
System.out.println("男人吃饭。");
}
} interface Boy extends People, Man { } //result
//男人吃饭

因为 Man 继承 PeopleMan 又重定了默认方法。很显然,这个时候,Boy 知道该继承谁的默认方法了。

注意,此时,如果用 People 通过 super 调用父类的 eat 方法会报错,因为调不到了

interface Boy extends People, Man {
@Override
default void eat() {
People.super.eat(); //People报错
System.out.println("男孩吃饭");
}
}

冲突三

Man 接口中新增一个方法:say,然后在 Boy 接口中新增一个默认方法:say

interface Man extends People{
default void eat() {
System.out.println("男人吃饭。");
}
void say(); //IDEA提示,say方法变灰,没有被使用
}

这时候,Man 中的抽象方法居然被忽略了,IDEA 都提示说没用到,这显然是默认方法优先于抽象方法。

总结

介绍了 Java 8 的默认方法静态方法,以及默认方法的冲突问题解决方案。

如果以后还说接口不能写实现方法,那就太OUT了。

Java8 新特性,打破你对接口的认知的更多相关文章

  1. Java8新特性

    Java8新特性 Java8主要的新特性涵盖:函数式接口.Lambda 表达式.集合的流式操作.注解的更新.安全性的增强.IO\NIO 的改进.完善的全球化功能等. 1.函数式接口 Java 8 引入 ...

  2. java8 新特性精心整理

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

  3. java8 新特性精心整理(全)

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

  4. Java8 新特性(三) - 日期时间对象以及一些其他特性

    日期时间对象 关于日期时间的操作可以分为两种: 转换:与字符串的互相转换,与时间戳的互相转换 计算:计算两个时间点之间的间隔.时间点与时间段的计算(计算下周N.下个月D日.去年M月D日等等) Java ...

  5. 【Java8新特性】Lambda表达式基础语法,都在这儿了!!

    写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...

  6. Lambad表达式--Java8新特性

    1.概述 Lambda是一个匿名函数,是java8的一个新特性.可以对接口进行非常简洁的实现.但它要求接口中只能有一个抽象方法,原因是lambda只能实现一个方法.另外,需要在接口上添加注解@Func ...

  7. java8新特性全面解析

    在Java Code Geeks上有大量的关于Java 8 的教程了,像玩转Java 8--lambda与并发,Java 8 Date Time API 教程: LocalDateTime和在Java ...

  8. Java系列 - 用Java8新特性进行Java开发太爽了

    本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome/ 前言 从开始写博客到现在已经过去3个 ...

  9. Java8 新特性之Stream----java.util.stream

    这个包主要提供元素的streams函数操作,比如对collections的map,reduce. 例如: int sum = widgets.stream() .filter(b -> b.ge ...

  10. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

随机推荐

  1. 有标号DAG计数(生成函数)

    有标号DAG计数(生成函数) luogu 题解时间 首先考虑暴力,很容易得出 $ f[ i ] = \sum\limits_{ j = 1 }^{ i } ( -1 )^{ j - 1 } \bino ...

  2. centos配置ssh服务并简单测试

    最近在做计算机集群方面的东西,简单弄了一下ssh服务. 首先把前提情况介绍一下: 1.我是用的虚拟机先模拟的,也不是没有真机,就是跑来跑去麻烦. 2.装了三个相同配置的centos虚拟机,详细参数就不 ...

  3. Dubbo 和 Spring Cloud 的区别?

    根据微服务架构在各方面的要素,看看 Spring Cloud 和 Dubbo 都提供了哪些支 持. Dubbo Spring Cloud 服务注册中心 Zookeep er Spring Cloud ...

  4. 什么是 JavaConfig?

    Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯 Java 方法.因此它有助于避免使用 XML 配置.使用 JavaConfig 的优点在 ...

  5. Redis 如何设置密码及验证密码?

    设置密码:config set requirepass 123456 授权密码:auth 123456

  6. Java 中的编译期常量是什么?使用它又什么风险?

    公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里 的 public 可选的.实际上这些变量在编译时会被替换掉,因为编译器知道这些 变量的值,并且知道这些变 ...

  7. 学习Puppet(一)

    puppet的入门 1.简介 puppet是一种采用C/S星状结构的linux.Unix平台的集中配置管理系统. puppet拥有自己的语言,可管理配置文件.用户.cron任务.软件包.系统服务等. ...

  8. instanceof关键字使用的方法(解决转型异常ClassCastException)

    一丶问题显现: 当你是父类的情况下,像使用子类的特定功能,就需要向下转型,但向下转型有可能会报错(ClassCastException) 而instanceof关键字就是解决异常的小能手,他能判断是否 ...

  9. scanf()格式化输入

    scanf();有种带[]的格式化输出方式 此格式控制符的基本格式为:%[scanfset] #include<stdio.h> int main() { char str[100] ; ...

  10. "双非"应届生校招如何获得大厂青睐?(内附前端大厂面经+技术岗超全求职攻略)

    写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路.故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有恐惧症的...等将来打算从事技术岗 ...