目录:

  • 接口的定义
  • 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年前的问题)

java接口的演变(jdk8的default、静态方法,jdk9的私有方法、私有静态方法)的更多相关文章

  1. 无所不能的PowerMock,mock私有方法,静态方法,测试私有方法,final类

    1.为什么要用mock 我的一本书的解释: (1)创建所需的DB数据可能需要很长时间,如:调用别的接口,模拟很多数据 (2)调用第三方API接口,测试很慢, (3)编写满足所有外部依赖的测试可能很复杂 ...

  2. Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type())

    Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type()) 一丶类的结构细分    ...

  3. 可能是把 Java 接口讲得最通俗的一篇文章

    读者春夏秋冬在抽象类的那篇文章中留言,"二哥,面试官最喜欢问的一个问题就是,'兄弟,说说抽象类和接口之间的区别?',啥时候讲讲接口呗!" 对于面向对象编程来说,抽象是一个极具魅力的 ...

  4. Java 接口和抽象类差别

    原文:http://blog.csdn.net/sunboard/article/details/3831823 1.概述 一个软件设计的好坏,我想非常大程度上取决于它的总体架构,而这个总体架构事实上 ...

  5. 使用PowerMockito和Mockito进行模拟测试,包括静态方法测试,私有方法测试等,以及方法执行的坑或者模拟不成功解决

    依赖:这个很重要,不同版本用法也有点区别: <dependency> <groupId>org.mockito</groupId> <artifactId&g ...

  6. JavaScript【面向对象】-静态方法-私有方法-公有方法-特权方法

    JavaScript面向对象是近年来比较火的一个概念了,由于小弟才疏学浅,虽然做过不少的web项目,看了网上很多深奥的资料和教程,还是对他们深奥 的理论一知半解,前段时间看了点书,总算有了自己的理解, ...

  7. JDK8新增接口的默认方法与静态方法

    JDK8之前,interface中可以定义常量和抽象方法,访问修饰符是public. public interface A { /** a1和a2写法是等价的 */ public static fin ...

  8. JDK8新特性之接口默认方法与静态方法

    接口默认方法与静态方法 有这样一些场景,如果一个接口要添加一个方法,那所有的接口实现类都要去实现,而某些实现类根本就不需要实现这个方法也要写一个空实现,所以接口默认方法就是为了解决这个问题. 接口静态 ...

  9. JDK8.0接口中的默认方法和静态方法

    我们在接口中通常定义的方法是抽象方法,即没有方法体,只有返回值类型和方法名:(public abstract) void Method(); 类在实现接口的时候必须重写抽象方法才可以 jdk8中新加的 ...

随机推荐

  1. PythonI/O进阶学习笔记_5.python的set和dict

    前言: 我一直觉得对我来说学习知识很忌讳不系统.本篇内容与上一篇 自定义序列类是有联系的. 上一篇比较通范的了解了序列类的一些协议和特性,并且有些list的内容.这篇更加具体到set和dict这两个序 ...

  2. FreeSql (二)自动迁移实体

    FreeSql 支持 CodeFirst 迁移结构至数据库,这应该是(O/RM)必须标配的一个功能. 与其他(O/RM)不同FreeSql支持更多的数据库特性,而不只是支持基础的数据类型,这既是优点也 ...

  3. 本地代码上传至github

    一. 环境及工具 1.下载并安装git版本管理工具 到 http://git-scm.com/downloads 下载并安装git版本管理工具 2.Windows客户端 3.配置github账号密码及 ...

  4. 在nginx日志access log可以记录POST请求的参数值

    1)      在nginx日志access log可以记录POST请求的参数值 实现程度:日志中可以显示POST请求所提交的参数值 问题: 日志中文显示十六进制(在配置文件中配置中文也无效) 没有对 ...

  5. Jmeter介绍和安装

    Apache JMeter™应用开源软件,100%纯Java应用程序,设计用于负载功能测试和性能测试.它最初是为测试Web应用程序而设计的,但后来扩展到其他测试函数中. 安装步骤:1.安装JDK 8版 ...

  6. Day 18 软件管理3之搭建网络仓库

    搭建一个网络仓库 服务端: 10.0.0.200   1.准备软件包( 1.光盘 2.缓存 3.联网下载 4.同步 ) 2.通过p共享软件包存放的目录 3.将光盘中的软件包都拷贝至p的共享目录下 4. ...

  7. Postman工具使用-接口测试(实战一)

    写在前面,本文首发[简书]https://www.jianshu.com/p/c188624c3580 作为一名测试人员,要去思考一下,如何能按需完成任务,又能轻松解决问题,这就很重要了!!! 凡事皆 ...

  8. Oracle中RMAN基本命令教程

    一.target--连接数据库 1.本地: [oracle@oracle ~]$ rman target / 2.远程: [oracle@oracle ~]$ rman target sys/orac ...

  9. Spring boot缓存初体验

    spring boot缓存初体验 1.项目搭建 使用MySQL作为数据库,spring boot集成mybatis来操作数据库,所以在使用springboot的cache组件时,需要先搭建一个简单的s ...

  10. 使用mkfs.ext4格式化大容量磁盘

    使用mkfs.ext4默认参数格式化磁盘后,发现格式化时间特别长,并且格式化会占用磁盘很大的空间.例如2TB的磁盘格式化会占用10分钟左右时间,并占用30G左右的磁盘空间.究其原因,原来inode会占 ...