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年前的问题)
java接口的演变(jdk8的default、静态方法,jdk9的私有方法、私有静态方法)的更多相关文章
- 无所不能的PowerMock,mock私有方法,静态方法,测试私有方法,final类
1.为什么要用mock 我的一本书的解释: (1)创建所需的DB数据可能需要很长时间,如:调用别的接口,模拟很多数据 (2)调用第三方API接口,测试很慢, (3)编写满足所有外部依赖的测试可能很复杂 ...
- Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type())
Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法),类方法,静态方法,属性) ,isinstance 和issubcalss ,元类(type()) 一丶类的结构细分 ...
- 可能是把 Java 接口讲得最通俗的一篇文章
读者春夏秋冬在抽象类的那篇文章中留言,"二哥,面试官最喜欢问的一个问题就是,'兄弟,说说抽象类和接口之间的区别?',啥时候讲讲接口呗!" 对于面向对象编程来说,抽象是一个极具魅力的 ...
- Java 接口和抽象类差别
原文:http://blog.csdn.net/sunboard/article/details/3831823 1.概述 一个软件设计的好坏,我想非常大程度上取决于它的总体架构,而这个总体架构事实上 ...
- 使用PowerMockito和Mockito进行模拟测试,包括静态方法测试,私有方法测试等,以及方法执行的坑或者模拟不成功解决
依赖:这个很重要,不同版本用法也有点区别: <dependency> <groupId>org.mockito</groupId> <artifactId&g ...
- JavaScript【面向对象】-静态方法-私有方法-公有方法-特权方法
JavaScript面向对象是近年来比较火的一个概念了,由于小弟才疏学浅,虽然做过不少的web项目,看了网上很多深奥的资料和教程,还是对他们深奥 的理论一知半解,前段时间看了点书,总算有了自己的理解, ...
- JDK8新增接口的默认方法与静态方法
JDK8之前,interface中可以定义常量和抽象方法,访问修饰符是public. public interface A { /** a1和a2写法是等价的 */ public static fin ...
- JDK8新特性之接口默认方法与静态方法
接口默认方法与静态方法 有这样一些场景,如果一个接口要添加一个方法,那所有的接口实现类都要去实现,而某些实现类根本就不需要实现这个方法也要写一个空实现,所以接口默认方法就是为了解决这个问题. 接口静态 ...
- JDK8.0接口中的默认方法和静态方法
我们在接口中通常定义的方法是抽象方法,即没有方法体,只有返回值类型和方法名:(public abstract) void Method(); 类在实现接口的时候必须重写抽象方法才可以 jdk8中新加的 ...
随机推荐
- Loadrunner 11 的安装
安装包可以直接在我的百度网盘下载,这里用的是LR11的版本.电脑系统是win7 链接: https://pan.baidu.com/s/1OApfUemG3oVjLUE79qaikw 提取码: 7n3 ...
- 剑指offer(五):用两个栈实现一个队列
题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解决办法: 队列先进先出,栈先进后出(stack1和stack2) 其实主要要注意的点是: ①在添加时直接 ...
- android.intent.category.BROWSABLE
参考: http://blog.csdn.net/annkie/article/details/8349626 http://xiechengfa.iteye.com/blog/1004991 BRO ...
- Net基础篇_学习笔记_第十一天_面向对象(构造函数)
VS封装字段快捷键: 提取方法 Ctrl+R,M 封装字段 Ctrl+R,E 提取接口 Ctrl+R,I. 构成函数: public Student() { Con ...
- 关于spring boot多张表建立外健的讨论
现在有四张表:student(学生表).blogs(博客表).comment(评论表).reply(回复表) 现在说一下这四张表: student(学生表):学生的信息记录表 blogs(博客表):学 ...
- 表达式树练习实践:C# 循环与循环控制
目录 表达式树练习实践:C# 循环 LabelTarget for / while 循环 无限循环 最简单的循环 多次循环 break 和 continue 一起 表达式树练习实践:C# 循环 C# ...
- Elastic Stack 笔记(七)Elasticsearch5.6 聚合分析
博客地址:http://www.moonxy.com 一.前言 Elasticsearch 是一个分布式的全文搜索引擎,索引和搜索是 Elasticsarch 的基本功能.同时,Elasticsear ...
- 41 (OC)* OC的理解与动态特性
1:动态类型(Dynamic typing),动态绑定(Dynamic binding)和动态加载(Dynamic loading). 动态类型:即运行时再决定对象的类型.简单说就是id类型.id类型 ...
- C++类拷贝控制 深拷贝 浅拷贝
普通类型对象之间的复制很简单,而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量,这篇文章将帮你理清C++类对象的拷贝方式 拷贝构造函数,拷贝赋值运算符 首先我们简单了解下默认的拷贝 ...
- Vue学习之todolist删除功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...