java接口的演变(jdk8的default、静态方法,jdk9的私有方法、私有静态方法)

目录:

  • 接口的定义
  • jdk7-9,接口属性的变化
  • jdk8,default、public static method的提出解决了什么问题,使用时需要注意什么
  • jdk9的补充(引入private method、private static method)
  • 新老生常谈:接口和抽象类的对比
  • 单继承还是多继承

 

一、接口的定义:

首先让我们看一下接口的最新定义:What is an Interface,里面提到:

In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces. 

再来看一下jdk1.7时的定义(具体原版定义官网已经找不到了,只能通过书籍及博客找到大概的版本):

An interface in Java is similar to a class, but the body of an interface can include only abstract methods and final fields (constants). A class implements an interface by providing code for each method declared by the interface.

我们知道,在Java中,接口不是类,而是对类的一组需求描述,类遵循接口描述的统一格式进行定义。Java不支持多继承,主要是为了避免多继承会让语言本身变得复杂(像C++),效率也会降低。而接口可以提供多继承的大多数好处,同时避免多重继承的复杂性和低效性。

通过对比上面两段定义,可以看出最新的接口多了一些新的属性,接下来主要围绕这些新属性来理解接口的定义。 


 

二、jdk7-jdk9,接口的变化:

然后再来简单看一下java interface的一个演变过程:

  • Constants (until Java 1.7)

  • Method signatures (until Java 1.7)

  • Nested types (until Java 1.7)

  • Default methods (since 1.8)

  • Static methods (since 1.8)

  • Private methods (since 1.9)

  • Private static methods (since 1.9) 


 

三、default和public static method:

接着我们先从一个8年前的问题开始:如果接口中有个方法的定义是可以确定的(实现该接口的类必须重复实现该方法),如何更优雅的设计这个接口?

文中提到了许多折中的方法:通过接口里的静态类、借助工具类的静态方法等。

但到了jdk8开始,这个问题被解决了:接口引入了default关键字和静态方法(public static method),接口中通过default修饰的方法可以有方法体,实现具体功能。看下面代码:

public interface Skill{
    void oldSkill();
    default public void newSkill(){
        System.out.print("实现了这个接口的类可以不实现这个方法");
    }
  public static newStaticSkiil(){
        System.out.print("实现了这个接口的类可以不实现这个静态方法");  
    }
}

引入default的目的官网有解释:Default Method ,总的来说,引入default关键字是为了当接口有新的行为且现有依赖该接口的类与接口不需做任何改变,可以不再对于已实现该接口的类或继承该接口的接口进行修改,可以更加方便的拓展现有接口。

文中还指出,对于拓展了包含default method的接口或类:

  • Not mention the default method at all, which lets your extended interface inherit the default method.(可以不理,直接继承)
  • Redeclare the default method, which makes it abstract.(重新声明为抽象方法)
  • Redefine the default method, which overrides it.(重新定义方法)

最后,还提到了jdk8开始,接口可以支持静态方法(public static method),这些都是为了接口可以有更好的演变性。

例如,jdk8开始引入的Lambda语法以及Stream API,都是在接口层实现的,因此default及public static method的提出算是为新的设计服务,也响应了这么久以来定义接口方法的呼声。

Collection接口中,default关键字的身影:

引入default关键字后,有些地方可能要注意一下。首先是如果类实现的多个接口都包含了对同一个方法的default定义,那这个方法必须重写,看下面例子:

public interface Ina {
    default void say(){
        System.out.println("say a");
    }
}
public interface Inb {
    default void say(){
        System.out.println("say b");
    }
}

如果classc在实现这两个接口时不重写say方法,那编译器无法确定到classc调用say方法时,选择哪一个接口的方法。因此Classc必须重写say:

public class classc implements Ina,Inb {
    @Override
    public  void say(){
        System.out.println("say c");   
    }
}

当然,根据上面提示的3条规则,我们也可以把say方法重新声明为抽象方法:

public interface Ind extends Ina{
    public abstract void say();
}

 

四、jdk9的补充:

jdk9中,接口引入的私有方法(private method)和私有静态方法(private static method)。由于不可被继承,因此私有方法必须定义方法体才有意义。同时也意味着接口的私有方法和私有静态方法不可被实现该接口的类或继承该接口的接口调用或重写。私有方法(private method)和私有静态方法(private static method)的提出都是对jdk8提出的default和public static method的补充。

默认方法和静态方法可以共享接口中的私有方法,因此避免了代码冗余,这也使代码更加清晰。如果私有方法是静态的,那这个方法就属于这个接口的。并且没有静态的私有方法只能被在接口中的实例调用。


 

五、接口和抽象类的区别:

抽象类定义:An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

jdk8之后,接口的行为不再局限在“描述”,接口的行为具有了“定义”,对后期接口的演变和拓展提供了便利性,也表示类的行为可以多继承了;当然即使是多了这些新特性,接口还是和抽象类有一条最明显的分界线:接口无状态,抽象类只能单继承。接口的成员域依然只能是常量,接口依然不能实例化。除此之外,还有权限上的区别,不支持protect声明及包可见等属性。


 

六、单继承还是多继承:

不过,接口的这些新属性是为了更好的服务“单继承多实现”的理念还是更好的往“多继承”靠拢呢?网上有很多不同的声音,而本人更倾向于更好的服务“单继承多实现”,我们知道,最大的改变还是jdk8提出的default和public static method,接口跳出了只能“声明”方法,只有public abstract method的界限,从而使得原有框架上多出了更多优雅的设计。打破的规则如果可以让Java更优雅,那这规则就是应该被打破的。

参考:

《Java核心技术 卷1》

https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

https://en.wikipedia.org/wiki/Interface_(Java)

More Power to Interface in Java 9

Java Interface-Implementation Pair(8年前的问题)

posted on 2018-08-05 16:38 西楼有酒 阅读(...) 评论(...) 编辑 收藏

导航