在JDK8中针对接口有做增强,在JDK8之前是这样的:
interface 接口名{
静态常量;
抽象方法;
}
JDK8之后对接口做了增加,接口中可以有默认方法和静态方法了,如下:
public interface TestInterface {
//常量:默认是 static final 的
String name = "hello";
//抽象方法,默认是public的
void test1();
//默认方法(注意:默认方法能调用静态方法和抽象方法 )
default void test02(){
System.out.println("我是默认方法");
test1();
test03();
}
//静态方法
static void test03(){
System.out.println("我是静态方法");
}
}
public class TestInterfaceImpl implements TestInterface{
@Override
public void test1() {
System.out.println("我是实现类");
}
// @Override
// public void test02(){
// System.out.println("我重新实现了默认方法");
//
// }
}
public static void main(String[] args) {
TestInterface.test03(); //调用静态方法
TestInterfaceImpl testInterface = new TestInterfaceImpl();
testInterface.test1(); //调用实现类方法
testInterface.test02(); //调用默认方法
}
通常基于抽象的概念设计中,抽象往往有多个实现,如果没有多个实现也不太必要去抽象。而且一个接口的实现必须实现该接口所有的抽象方法,这并不是一个可选择的行为,如果我们在一个接口中增加了新的方法就会影响到其所有的实现类,很可能有些实现类根本不需要这个功能,但是又不得不去实现该功能。
接口默认方法是解决这个问题的有效方式。它允许在接口中直接添加一个功能实现,并且所有的实现类都可以使用这个功能实现而无需修改这些实现类。通过这种方式,可以巧妙地保留向后兼容性。另外这也是扩展函数式接口的唯一方法,如果没有默认方法,一旦函数式接口需要扩展就会引发“灾难性”的连锁反应。
这样说来默认接口方法确实是一个非常好的特性,但是还是有一些需要我们注意的问题。由于 Java 允许类实现多个接口,当一个类实现多个定义相同默认方法的接口时会发生什么情况? 会议引发**方法签名引起的冲突, **解决办法是在子接口中从新定义这个默认方法
假设我们定义一个动物接口,他的子类有猫,狗,兔子, 此刻有一天我想让兔子飞但是又不想其他动物飞,至于其他动物而是等以后在说
那么在以前没有默认方法的时候我们只能在兔子这个实现类中定义一个他自己的私有飞的方法,突然有一天我又想让猫飞了那么还需要在这个猫里面定义一个私有的方法
现在有了默认的方法,我们只需要在接口里定义好飞的默认方法就行,然后在需要飞的时候通过对象.默认方法`就行,这样就不会影响到原有的代码了
说到这里回到主题为啥需要在接口中添加静态方法呢? ,我们在其他类中也能添加静态方法, 原因很简单是作用范围(概念上的), 为什么会这么说,因为我想给所有动物添加一个通用方法那么我静态方法该定义到哪里? 狗? ,还是猫? 是不是感觉都不是很合适,这时候你会想到既然是通用的那么我放在动物接口里不更好
就比如说Spring Security架构的默认配置机制就是这样实现的
@FunctionalInterface
public interface Customizer<T> {
void customize(T t);
static <T> Customizer<T> customizeDefaults() {
return (t) -> {
};
}
}
如果你使用默认配置你可以直接通过静态方法实现,如果你想自定义就通过实现抽象接口,这样统一的范式就能够稳定下来了,一般作为一种功能的辅助手段,而且这种手段不能被改写。
