什么是默认方法
- java8引入了一个新的功能,叫默认方法,通过默认方法你可以指定接口方法的默认实现。换句话说:就是接口可以提供具体的实现。
- Java8允许在接口内申明静态方法。
排序处理:
List<Integer> sorts = Arrays.asList(1,34,5,3,45);
sorts.sort(Comparator.naturalOrder());
sorts.forEach(s-> System.out.println(s));
sorts.sort(Comparator.comparingInt(Integer::intValue));
sorts.forEach(s-> System.out.println(s));
sorts.sort(Comparator.comparing(Integer::byteValue));
sorts.forEach(s-> System.out.println(s));
在接口里面定义默认方法的作用简单来说就是为了向后兼容,默认接口是不用去强制实现的。
如何以一种兼容的方式改进API
来看一个例子,设计一个绘图的API接口
public interface Resizable extends Drawable{
/**
* 设置高度
*
* @param high
*/
void setHigh(int high);
/**
* 设置宽度
*
* @param width
*/
void setWidth(int width);
/**
* 获取高度
*
* @return
*/
int getHigh();
/**
* 获取宽度
*
* @return
*/
int getWidth();
/**
* 设置绝对位置
*
* @param high
* @param width
*/
void setAbsoluteSize(int high, int width);
}
有绘长方形,圆形分别来实现这个接口
public class Rectangle implements Resizable {
@Override
public void setHigh(int high) {
}
@Override
public void setWidth(int width) {
}
@Override
public int getHigh() {
return 0;
}
@Override
public int getWidth() {
return 0;
}
@Override
public void setAbsoluteSize(int high, int width) {
}
@Override
public void draw() {
}
}
public class Square implements Resizable {
@Override
public void setHigh(int high) {
}
@Override
public void setWidth(int width) {
}
@Override
public int getHigh() {
return 0;
}
@Override
public int getWidth() {
return 0;
}
@Override
public void setAbsoluteSize(int high, int width) {
}
@Override
public void draw() {
}
}
如果需求发生变化,API接口需要新添加一个获取相对位置的方法,那对于接口的实现来说就是灾难。每一个接口的实现都需要实现这个方法。但是,对于有些实现来说是毫无意义的,因此有了默认接口的。
/**
* add fix 设置相对位置
*/
default void setRelativeSize(int wFactor,int hFactor){
wFactor = getWidth()/wFactor;
hFactor = getHigh()/hFactor;
setAbsoluteSize(wFactor,hFactor);
}
- 抽象类和抽象接口的区别
首先,一个类只能继承一个抽象类,可以实现多个接口
其次,一个抽象类可以存在实例变量,接口是不能有实例变量
默认方法的使用模式
- 可选方法
利用默认方法可以去除掉对接口的无用实现。对于接口里面的可选方法可以设置为默认方法,这样就不用在接口实现里出现空方法。 - 行为的多继承
类型的多继承,Java8之前就可以实现类型的多继承,一个类是可以同时实现多个接口的。
利用正交方法精简接口
组合接口
解析规则
由于Java一个类可以实现多个接口,现在一个接口里面可以有方法的具体实现,
这样就会出现,一个类继承了多个方法而它们使用的却是同样的函数签名。
解决这个问题有三条规则:
- 类中的方法优先级最高。类或者父类中声明的方法的优先级高于任何申明为默认方法的优先级。
- 子类的优先级更高,函数签名相同时,优先选择拥有最具体实现的默认方法的接口。
- 上面两条还是无法区别的话,必须显示指明。