接口中的默认方法与静态方法
写在前面
在Java8之前,接口没有任何具体的实现。
《JAVA编程思想》中是这样描述的:“interface这个关键字产生了一个完全抽象的类,它根本就没有提供任何具体的实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。接口只提供一种形式,而为提供任何具体的实现”。
但是在Java8中,对接口做了很大的的改动,接口中允许定义默认方法和静态方法了。
默认方法
以前接口中只能有全局静态常量和抽象方法,现在Java8的接口中可以拥有实现的方法了即默认方法。
接口的默认方法有助于在扩展系统功能的同时,不对现有的继承关系以及类库产生很大影响。比如,在JDK1.8中,Java集合框架的Collection接口增加了stream()等默认方法,这些默认方法即增强了集合的功能,又能保证对低版本的JDK的兼容。
下面为Collection接口的stream()方法源码:
接口默认方法的语法:
default 关键字 methodName(参数列表) {//要实现的方法体}
在Java8中,因为存在函数式接口,一个接口中只能存在一个普通方法,但是可以写多个默认方法,来为实现类提供方法实现。
public interface MyInterface {
//默认方法
default String getName(){
return "张三";
}
//默认方法
default Integer getAge(){
return 18;
}
//普通方法
String getSomething();
}
既然接口中可以方法的实现,那么就会出现与父类之间进行冲突的问题。
public class MyClass {
//默认方法
public String getName(){
return "李四";
}
}
上面类中也有一个getName()方法,如果有一个类即实现了MyInterface接口又继承了MyClass类,我们想一下,这时候getName()方法是使用接口中的还是父类中的呢?
public class TestDefaultMethod extends MyClass implements MyInterface {
@Override
public String getSomething() {
return null;
}
public static void main(String[] args) {
TestDefaultMethod tfm = new TestDefaultMethod();
System.out.println( tfm.getName());//打印输出了李四,说明调用的是父类的方法
}
}
运行结果说明调用的是父类的方法。这里有一个类优先原则。
什么是“类优先”原则呢?若一个接口中定义了一个默认方法,而另一个父类又定义了一个同名的方法时,则优先调用父类的方法。
如果我们再定义一个接口,里面也有一个方法叫做getName,而一个类去同时实现这两个接口。那么这个类的 getName 方法到底会执行哪一个呢?
public interface MyInterface2 {
//默认方法
default String getName(){
return "张三2";
}
}
public class TestDefaultMethod2 implements MyInterface, MyInterface2 {
//同名方法的接口要求我们必须重写,不重写就会报错了
@Override
public String getName() {
return MyInterface2.super.getName();
}
//普通方法
@Override
public String getSomething() {
return null;
}
public static void main(String[] args) {
TestDefaultMethod2 tfm2 = new TestDefaultMethod2();
System.out.println(tfm2.getName());//打印输出了李四,说明调用的是父类的方法
}
}
此时,类会让我们自己去重写,自己去选择使用上面2个接口中的方法。
若一个接口中定义了一个默认方法,而另外一个接口中又定义了一个同名方法时,就会发生接口冲突。不管是否是默认方法,那么必须覆盖该方法来解决冲突。
静态方法
在Java 8中,接口中还允许添加静态方法
MyInterface接口中加一个静态方法
public interface MyInterface {
//默认方法
default String getName(){
return "张三";
}
//静态方法
public static void method(){
System.out.println("这个是静态方法");
}
//普通方法
String getSomething();
public static void method(){
System.out.println("这个是静态方法");
}
}
测试静态方法的调用
public class TestMe {
public static void main(String[] args) {
//父接口.方法这种格式调用
MyInterface.method();//打印输出 这个是静态方法
}
}