Java8——接口的默认方法和静态方法

Java8接口新特性

interface 的设计初衷是面向抽象,提高扩展性。但缺点就是Interface 修改的时候,实现它的类也必须跟着修改。

为了解决接口的修改与现有的实现不兼容的问题。Java 8在接口声明的时候增加了两个新的概念:默认和静态方法。

新 interface 的方法可以用default 或 static修饰,一个 interface 中可以有多个方法被它们修饰,这 2 个修饰符的区别主要也是普通方法和静态方法的区别。

  • default修饰的方法,是普通实例方法,可以用this调用,可以被子类继承、重写。
  • static修饰的方法,使用上和一般类静态方法一样。但它不能被子类继承,只能用Interface调用。

默认方法允许我们在接口里添加新的方法,而不会破坏实现这个接口的已有类的兼容性,也就是说不会强迫实现接口的类实现默认方法。

默认方法和抽象方法的区别是抽象方法必须要被实现,默认方法不是。作为替代方式,接口可以提供一个默认的方法实现,所有这个接口的实现类都会通过继承得到这个方法(如果有需要也可以重写这个方法)

我们来看一个实际的例子。

public interface InterfaceNew {
    default void def() {
        System.out.println("interface default方法");
    }
   
}

public interface InterfaceNewImpl1 implements InterfaceNew{
    
}
public interface InterfaceNewImpl2 implements InterfaceNew{
    public void def() {
        System.out.println("interface InterfaceNewImpl2方法");
    }
  
}

接口InterfaceNew使用default关键字声明了一个默认方法def(),类InterfaceNewImpl1实现了InterfaceNew接口,没有对默认方法做任何修改。另外一个类InterfaceNewImpl2重写类默认实现,提供了自己的实现方法。

Java 8 的另外一个有意思的新特性是接口里可以声明静态方法,并且可以实现。例子如下:

public interface InterfaceNew { 
   static void sm() {
        System.out.println("interface提供的方式实现");
    }

}

下面是把接口的静态方法和默认方法放在一起的示例:

public interface InterfaceNew {
    default void def() {
        System.out.println("interface default方法");
    }
    default void def2() {
        System.out.println("interface default2方法");
    }
    static void sm() {
        System.out.println("interface提供的方式实现");
    }
    static void sm2() {
        System.out.println("interface提供的方式实现");
    }

    
    //需要实现类重写
    void f();
}

public interface InterfaceNew1 {
    default void def() {
        System.out.println("InterfaceNew1 default方法");
    }
}

如果有一个类既实现了 InterfaceNew 接口又实现了 InterfaceNew1接口,它们都有def(),并且 InterfaceNew 接口和InterfaceNew1接口没有继承关系的话,这时就必须重写def()。不然的话,编译的时候就会报错。

public class InterfaceNewImpl implements InterfaceNew , InterfaceNew1{
    public static void main(String[] args) {
        InterfaceNewImpl interfaceNew = new InterfaceNewImpl();
        interfaceNew.def();
    }

    @Override
    public void def() {
        InterfaceNew1.super.def();
    }

    @Override
    public void f() {
    }
}

JVM平台的接口的默认方法实现是很高效的,并且方法调用的字节码指令支持默认方法。默认方法使已经存在的接口可以修改而不会影响编译的过程。java.util.Collection中添加的额外方法就是最好的例子:stream(), parallelStream(), forEach(), removeIf()

在Java8 中接口和抽象类有什么区别的?

很多小伙伴认为:“既然 interface 也可以有自己的方法实现,似乎和 abstract class 没多大区别了。”

其实它们还是有区别的:

  • 接口是多实现,而抽象类是单继承
  • 接口的方法是 public abstract 修饰,变量是 public static final 修饰。 而抽象类可以用其他修饰符
  • 接口的方法是更像是一个扩展插件。而抽象类的方法是要继承的。

开始我们也提到,interface 新增default和static修饰的方法,为了解决接口的修改与现有的实现不兼容的问题,并不是为了要替代abstract class。在使用上,该用 abstract class 的地方还是要用 abstract class,不要因为 interface 的新特性而将之替换。

参考:

Java8 新特性实战 | JavaGuide(Java面试 + 学习指南)

Java 8 特性 – 终极手册 | 并发编程网 – ifeve.com

你可能感兴趣的:(Java8新特性,开发语言,java)