时间:2021-05-20
在Java SE 8之前,接口中是不能提供方法实现的,但是JDK8提供了接口的默认方法和静态方法的支持。
默认方法
方法前加default关键字就可以提供默认实现,类实现接口时,可以继承接口的默认方法,也可以覆盖默认方法。
interface People { default void eat(String name) { System.out.println(name + " is eating."); }}抽象类也可以提供方法的默认实现,一个类可以同时继承一个抽象类和多个接口,如果抽象类和接口中存在相同的方法时会怎么样呢?
一个抽象类和多个接口
如果类继承了抽象类,采取类优先的原则,优先继承抽象类的方法。我们在编写类的时候会发现,必须先extends类再implements接口,否则工具会提示extends的错误。不论抽象类的方法有没有提供默认实现,类都会继承抽象类的方法,就算接口的方法提供了默认实现,也完全不关心。
接口A,B:
interface A { default void eat() { System.out.println("A"); }}interface B { default void eat() { System.out.println("B"); }}抽象类C:
abstract class C { public void eat() { System.out.println("C"); }}测试类Test:
public class Test extends C implements A, B { public static void main(String[] args) { Test test = new Java8Test(); test.eat(); }}输出结果:
C
程序输出C说明Test类继承了抽象类C的eat方法的实现。
当抽象类C不提供eat方法的默认实现并且Test类不提供eat方法的重写时,编译器是不会放过Test类的,明明继承了C类,却不提供抽象方法的实现。编译器不会关心Test是否还实现了其他接口并且接口中有相同方法,一码归一码。
那么如果是抽象类提供了默认实现,接口没有提供呢?
我们让抽象类C实现eat方法,接口A只提供一个接口,类Test不重写eat方法。
接口A,B:
interface A { void eat();}interface B { default void eat() { System.out.println("B"); }}抽象类C:
abstract class C { public void eat() { System.out.println("C"); }}测试类Test:
public class Test extends C implements A, B { public static void main(String[] args) { Test test = new Test(); test.eat(); }}运行main方法,控制台打印出抽象类中eat方法的输出结果。
其实我们可以这么理解,编译器总要一步一步的编译,首先编译到extends,检查所有的抽象方法是否被重写,有没被重写的方法就抛出编译错误,否则就继续编译。当编译到implements时,类Test已经是拥有抽象类C所有方法的实现了,即已经提供了接口A和B中相同方法的重写。
以上总结就是抽象类和接口的方法冲突时以抽象类为准就是了。如果抽象类不在了,两个接口方法冲突了,该听谁的呢?
多个接口
接口A提供方法默认实现,接口B只提供方法。
接口A、B:
interface A { default void eat() { System.out.println("A"); }}interface B { default void eat() { System.out.println("B"); }}测试类Test:
public class Test implements A, B { public static void main(String[] args) { Test test = new Test(); test.eat(); }}此时编译器提示,类Test从类型A和B中继承了eat()的不相关默认值。也就是说,当两个接口冲突时,编译器无法判断继承A还是继承B的方法实现。这时候,类Test就需要自己提供eat()方法的实现了。
静态方法
接口中也可以提供静态方法,使用static关键字。类不能继承接口的静态方法,所以也不存在覆盖静态方法。访问静态方法时通过接口访问,即People.eat(“name”)。
interface People { static void eat(String name) { System.out.println(name + " is eating."); }}可以测试一下,调用继承了People接口的类实例的eat方法,工具提示不能通过类实例访问静态成员。或者试着重写一个eat方法并加上@Override注解,工具提示“Method does not override method from its superclass”。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java8新特性内建函数式接口 在之前的一片博文Lambda表达式,提到过Java8提供的函数式接口。在此文中,将介绍一下Java8四个最基本的函数式接口
一、Lambda表达式简介Lambda表达式,是Java8的一个新特性,也是Java8中最值得学习的新特性之一。(另一个新特性是流式编程。)Lambda表达式,
前言在看一本关于高性能编程的时候发现Java8中关于接口的新特性的介绍,这个特性是真的棒,解决了一个接口中有多个方法,但并不想实现该接口的类都去实现所有的方法,
为什么要单独写个Java8新特性,一个原因是我目前所在的公司用的是jdk8,并且框架中用了大量的Java8的新特性,如上篇文章写到的stream方法进行过滤ma
前言在Java8之前,默认情况下,接口中的所有方法都是公共的和抽象的。但是这一限制在Java8中被打破了,Java8允许开发人员在接口中添加新方法,而无需在实现