一、概述
java为了引入函数式编程的特性在java8中引入了一个全新的概念“lambda表达式”,同时为了使“lambda表达式”与现有的类库无缝结合,引入了default关键字,允许在接口中定义default的默认实现方法,同时允许在接口中定义static静态实现方法,这两者在java7中是不允许的。lambda表达式从语法层面看极大的简化了匿名内部类的使用,将匿名内部类声明过程中冗余的代码都消灭了,从编译器和代码底层执行层面看,lambda表式有利于编译器优化,充分利用多核CPU的特性进行并行处理。允许在接口中定义default方法和static方法使得接口扩展变得更加轻松。另外Java8通过Lambda表达式提供了对类似于JavaScript中的Function对象和闭包的直接支持。
二、default方法与static方法
在接口中定义default方法使得接口具备抽象类的“功能”,即为子类的实现提供默认的方法实现,子类可以像调用自身的方法一样调用这些默认的实现方法,但两者的动机与语义是完全不同的。前者的动机在于扩展已有接口,使得已有接口在不增加新的抽象方法的前提下增加新的实现方法,而后者则主要是为了简化子类的实现,将子类中的公共方法实现或者某些相对不怎么重要的方法的空实现集中起来放在抽象类中,由子类继承自抽象类,子类覆盖符合子类特性的方法。
2.1 default方法与static方法的相互调用
interface A{
//接口中可以定义变量,默认是public static final,必须初始化,可以加final,static,public修饰
final int i=1;
void test();
default void printA(){
System.out.println("A"+i);
}
default void printC(){
System.out.println("C");
//默认方法中可以访问静态方法或者默认方法
printB();
printA();
}
//default,static,abstract三个关键字中不能同时有两个关键字修饰一个方法
// default static void printD(){
// System.out.println("C");
// }
static void printB(){
//static方法中不能访问default方法,只能访问静态方法
// printC()
System.out.println("静态方法A");
}
static void printD(){
printB();
}
}
由以上代码可知,接口中static方法只能访问static方法,不能访问default方法,而default方法可以访问static方法和default方法,调用方式跟普通类中调用方法一样。另外一个方法只能被static、default、abstract关键字修饰,因为从语义上讲,static方法就是一种静态的default方法,是一种已经实现的方法,与abstract定义的抽象方法冲突。
2.2 接口继承下static方法与default方法的继承与覆写
interface E extends A{
@Override
default void printA(){
//printC()执行时会调用E中的printA方法,形成死循环
// printC();
A.super.printA();
System.out.println("接口间默认方法的继承");
}
//不允许覆写static方法
// @Override
// static void printC(){
// System.out.println("覆写静态方法C");
// }
}
由以上代码可知,子接口可以覆写父接口中的default方法,不能覆写父类中的static方法,子接口中可以像子类调用父类中的方法一样调用父接口中的default方法和static方法,通过A.super.printA()方法显示调用父类中的同名方法。
2.3 实现类同时继承了子接口和父接口
class D2 implements A,E{
@Override
public void test() {
System.out.println("D2");
}
}
public static void main(String[] args) {
D2 d2=new D2();
d2.printA();
d2.printC();
}
A1
接口间默认方法的继承
C
静态方法A
A1
接口间默认方法的继承
从执行结果看,实现类调用了子接口而不是父接口中的printA()方法,即当实现类继承的多个接口中存在同名的default方法时采用“最具体实现原则”,子类中的同名方法默认比父类中的方法更具体。另外值得注意的是,printC在执行的过程中父类的printA方法被自动替换为子类的printA方法。
2.4 实现类继承了两个接口,其中一个接口的抽象方法是另一个接口的default方法
interface C{
void printA();
}
class F implements A,C{
@Override
public void printA() {
System.out.println("默认方法不太代替接口实现");
}
@Override
public void test() {
System.out.println("test");
}
}
首先同一接口中抽象方法、default方法、static方法不能同名,由上述代码可知,同一实现类继承自两个不同的接口时,假如其中一个接口的抽象方法与另一个接口的default方法相同时,在实现类中default方法不能代替抽象方法的具体实现,具体而言printA()方法必须被实现,实现printA()方法的同时继承自A的default方法就被覆写了。
2.5、实现类继承两个独立的接口,两个接口具有相同的default方法
interface B{
void test();
default void printA(){
System.out.println("同名方法B");
}
static void printB(){
System.out.println("