扫描关注公众号查看更多内容
近期在研读《Java 8 in Action》中文版(中文《java8实战》),感觉受益良多,故想向大家分享这本书籍,并写下自己的对于其中的理解。
前言
其实说到java8新特性,有学过的同学都应该知道在java8中新增在接口中可以有默认方法了,所谓的默认方法就是用default修饰的方法。例如:
public interface Factory{
default void test(){
xxxx
}
}
那么默认方法的用处是什么呢?
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
作用
默认方法可以在接口中有具体的实现,那么在一个类实现这个接口时,并不需要强制必须的实现这个方法,当没有在这个类中实现这个方法时,调用时就采用接口中的这个默认实现。
public interface Vehicle {
default void print(){
System.out.println("我是一辆车!");
}
}
在实现类中可以定义默认方法来重写覆盖
public class Car implements Vehicle{
default void print(){
System.out.println("我是一辆四轮汽车!");
}
}
或者可以直接指定调用的默认方法
public class Car implements Vehicle{
public void print(){
super.print();
}
}
具体作用
例如在代码中定义了一个车型接口,在这个接口中有个print()的方法,方法作用是打印出自己车型的发动机类型,那么问题来了,自行车也是一种车型,但是它又没有发动机,那怎么实现这个方法呢?难道我们在自行车类中写一个空实现吗?
所以默认方法的作用不就来了。
实现“多继承”
这样是不是和类继承的重写规则有点像呢!!
如我们所知,一个类只能继承一个类,但是可以实现多个接口
那么,在我们所熟知的java只用单继承没有多继承就有了答案了,我们可以利用这个默认方法来实现“多继承”了!
代码如下
public interface Vehicle {
default void print(){
System.out.println("我是一辆车!");
}
}
public interface FourWheeler {
default void print(){
System.out.println("我是一辆四轮车!");
}
}
方法一
public class Car implements Vehicle, FourWheeler {
default void print(){
System.out.println("我是一辆四轮汽车!");
}
}
方法二
public class Car implements Vehicle, FourWheeler {
public void print(){
Vehicle.super.print();
}
}
注意事项
当我们想要实现多继承后,又有新的问题来了,当我们实现的多个接口中有同样的默认方法时,我们具体调用的是哪一个呢?
三条准则
当我们又有实现接口又有继承类时,那么当有同样的默认方法时,优先级最高的则是类中或者父类中的方法。
如果第一条不满足,如果实现的多接口中,接口之间有继承关系,那么子接口的优先级更高。
如果前两条都不满足,那么在本类中需要有重写覆盖的该方法或者直接直接调用指定的方法,否则编译器将报错!!
谨记
总结
1.Java 8中的接口可以通过默认方法和静态方法提供方法的代码实现。
2.默认方法的开头以关键字default修饰,方法体与常规的类方法相同。
3.向发布的接口添加抽象方法不是源码兼容的。
4.默认方法的出现能帮助库的设计者以后向兼容的方式演进API。
5.默认方法可以用于创建可选方法和行为的多继承。
6.我们有办法解决由于-一个类从多个接口中继承了拥有相同函数签名的方法而导致的冲突。
7.类或者父类中声明的方法的优先级高于任何默认方法。如果前- - 条无法解决冲突,那就选择同函数签名的方法中实现得最具体的那个接口的方法。
8.两个默认方法都同样具体时,你需要在类中覆盖该方法,显式地选择使用哪个接口中提供的默认方法。