一. 简介
jdk1.8以前,只允许在接口中定义两种类型的数据: 全局静态变量和抽象方法。但在jdk1.8中引入了两个全新的概念:
1. 在接口中可以使用default关键字修饰非抽象方法。
2. 接口内可以编写静态方法,并且可以被实现。
二. 接口中的默认方法
这里需要介绍几种场景:
1. 若一个类既继承了某个类的方法,同时也实现了某个接口的相同方法头的非抽象方法,那么根据类优先原则,最终执行的是继承自父类的方法。请看案例:
public interface MyFun {
default String getName(){
return "MyFun1";
};
}
public class MyClass {
public String getName(){
return "MyClass";
}
}
public class Test extends MyClass implements MyFun{
//MyClass中的getName()方法对MyFun()中的getName()方法进行了实现!
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.getName()); //输出MyClass
}
}
值得注意的是,如果父类中定义的方法和接口中定义的非抽象方法只是方法签名相同,那么java编译阶段都无法通过。这是因为Test类从MyClass中继承而来的public String getName()方法被编译器视作是对MyFun中getName()方法的实现!但由于两个方法的返回值类型不同(Double和String),即便是退而求其次,想在Test类中实现MyFun1的public String getName()方法都做不到,这是因为只有返回值类型不同,但方法签名相同,无法构成重载,因此编译器只能提示报错。
public interface MyFun1 {
default String getName(){
return "MyFun1";
};
}
public class MyClass {
public Double getName(){
return 2.0;
}
}
public class Test extends MyClass implements MyFun1{ //这里编译报错
}
2. 若一个类同时实现了多个接口,其中一个接口提供了默认方法,而另一个接口也提供了一个相同方法签名的方法,那么在使用方法使,必须指明调用的接口,哪怕其中某个接口的方法不是默认方法。
public interface MyFun1 {
default String getName(){
return "MyFun1";
};
}
public interface MyFun2 {
String getName();
}
public class Test implements MyFun1,MyFun2{
@Override
public String getName() {
//必须指明到底调用哪个接口的getName()方法
return MyFun1.super.getName();
}
}
Tips:
1. 方法签名: 方法名称 + 形式参数
2. 方法头: 访问修饰符 + 返回值类型 + 方法名称 + 形式参数
三. 接口中的静态方法
直接看例子:
public interface MyFun1 {
static Double getTotal(){ //访问修饰符可以省略,默认public
return 88.8;
}
}
class Test{
public static void main(String[] args){
Double result = MyFun1.getTotal(); //和调用类中的静态方法没任何区别
}
}