JavaSE-Lambda表达式-02-201804
1.默认接口方法(default interface method)
背景:lambda表达式和方法引用大大提升了Java的表达能力(expressiveness),不过为了使把代码即数据(code-as-data)变的更加容易,我们需要把这些特性融入到已有的库之中,以便开发者使用。但是接口发布之后已定型,若要向接口添加新方法,则必须将以往所有该接口的实现同样添加此新方法,这样工程量就太大了。
默认方法(之前被称为虚拟扩展方法或守护方法)的目标即是解决这个问题,使得接口在发布之后仍能被逐步演化。
默认方法利用面向对象的方式向接口增加新的行为。它是一种新的方法:接口方法可以是抽象的或是默认的。默认方法拥有其默认实现,实现接口的类型通过继承得到该默认实现(如果类型没有覆盖该默认实现)。此外,默认方法不是抽象方法,所以我们可以放心的向函数式接口里增加默认方法,而不用担心函数式接口的单抽象方法限制。
例如:Comparator接口中新增的默认方法Comparator<T> reversed()--比较器的逆序实现
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
解析:所有实现Comparator接口的类,都将继承默认方法Comparator<T> reversed(),使用者可以根据情况决定是否重写该方法。
注:当接口继承其它接口时,我们既可以为它所继承而来的抽象方法提供一个默认实现,也可以为它继承而来的默认方法提供一个新的实现,还可以把它继承而来的默认方法重新抽象化。
2.静态接口方法(static interface method)
Java SE 8还在允许在接口中定义静态方法。这使得我们可以从接口直接调用和它相关的辅助方法(Helper method),而不是从其它的类中调用(之前这样的类往往以对应接口的复数命名,例如:Collections)。
例如:
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
3.继承默认方法
和其它方法一样,默认方法也可以被继承。当类型或者接口的超类拥有多个具有相同签名的方法时,我们就需要一套规则来解决这个冲突:
a.类的方法(class method)声明优先于接口默认方法。无论该方法是具体的还是抽象的。
b.被其它类型所覆盖的方法会被忽略。这条规则适用于超类型共享一个公共祖先的情况。
/**
* 1.当实现One,Two,Three三个接口时,编译不过,原因是Two,Three中的default方法签名相同导致冲突
* 2.类的方法(class method)声明优先于接口默认方法。无论该方法是具体的还是抽象的
* */
public class Lambda02 extends Lpapa implements One,Two{
//此时Two中的plus()方法覆盖了其父接口One的plus()方法
public static void main(String[] args) {
Lambda02 la=new Lambda02();
la.plus(); //打印出two
la.minus(); //打印处lpapa 类Lpapa的方法覆盖了interface Two中的minus()
}
@Override
public void one() {
// TODO Auto-generated method stub
}
}
class Lpapa{
int n;
public void minus(){
System.out.println("lpapa");
}
}
interface One{
void one();
default void plus(){
System.out.println("one");
}
}
interface Two extends One{
default void plus(){
System.out.println("two");
}
default void minus(){
System.out.println("two-minus");
}
}
interface Three{
void three();
default void plus(){
System.out.println("three");
}
}
参考:http://www.cnblogs.com/figure9/p/java-8-lambdas-insideout-language-features.html