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. Nextcloud fpm 版在 Dokcer 下安装踩坑

    安装 首先到 https://registry.hub.docker.com/_/nextcloud 获取 Nextcloud 的示例 docker-compose version: '2' volu ...

  2. 半吊子菜鸟学Web开发3 --Html css学习1

    1创建一个html文件,用vscode打开 首先输入一个! 然后就可以开始编辑html文件了 2 整体结构 <!DOCTYPE HTML><html>    <head& ...

  3. 面试之Java String 编码相关

    实话说,作为一个多年Java老年程序员,直到近来,在没有决心花时间搞清楚Java String的编码相关问题之前, 自己也都还是似懂非懂,一脸懵逼的.设想如果在面试中,有同学能够条理清晰的回答下面的问 ...

  4. 请描述一下Struts2的值栈结构,以及它是如何工作的?

    值栈 Value Stack 值栈是Struts2框架的核心概念.所有的核心组件都以某种方式与之进行交互,它提供对上下文信息和执行环境中元素的访问机制.值栈的内容由如下4个层级组成. 1.临时对象 这 ...

  5. Dubbo 和 Spring Cloud 的区别?

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

  6. 使用redis作为django缓存数据库

    1.Redis的Windows版本.打开https://github.com/MSOpenTech/redis/releases下载msi安装包.该版本是64位.安装msi过程中,有个选项是否加入系统 ...

  7. SaltStack项目实战(一)

      系统架构图 一.初始化 1.salt环境配置,定义基础环境.生产环境(base.prod) ? 1 2 3 4 5 6 7 8 9 10 vim /etc/salt/master 修改file_r ...

  8. springboot项目如何添加热部署

    环境jdk1.8.maven3.6.使用工具为idea 1.在pom.xml文件中添加依赖 <dependency> <groupId>org.springframework. ...

  9. 常用 adb 命令总结

    1. 显示当前运行的全部模拟器:    adb devices    2.  安装应用程序:      adb install -r 应用程序.apk    3.  获取模拟器中的文件:      a ...

  10. 【Android Studio】Gradle统一管理版本号引用配置

    1.在根目录下的build.gradle文件下添加 ext{ .... } 中的内容 ...... // Define versions in a single place ext { // SDK ...