Java8新特性之四:接口默认方法和静态方法
在JDK1.8以前,接口(interface)没有提供任何具体的实现,在《JAVA编程思想》中是这样描述的:“interface这个关键字产生了一个完全抽象的类,它根本就没有提供任何具体的实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。接口只提供了形式,而未提供任何具体实现”。
但是这一限制在JDK1.8中被打破了,JDK1.8开始,接口允许定义默认方法和静态方法。
接口默认方法的语法很简单,即:
default关键字 methodName(参数列表) { // 实现体 }
接口静态方法语法与类的静态方法类似,不同的是接口静态方法的修饰符只能是public。
1、默认方法
为了提高代码的可重用性。接口的默认方法有助于在扩展系统功能的同时,不对现有的继承关系及类库产生很大的影响。例如在JDK1.8中,Java集合框架的Collection接口增加了stream()等默认方法,这些默认方法即增强了集合的功能,又能保证对低版本的JDK的兼容。
举个简单的例子,假如有一个Animal接口其中有fly()和swim()方法,有一个鸟类Bird和一个鱼类Fish同时实现这个接口,代码如下:
Animal接口:
public interface Animal {
void run();
void swim();
}
Bird.java
public class Bird implements Animal {
@Override
public void swim() {
// do nothing
}
@Override
public void fly() {
System.out.println("birds can fly...");
}
}
Fish.java
public class Fish implements Animal {
@Override
public void swim() {
System.out.println("fish can swim......");
}
@Override
public void fly() {
// donothing
}
}
从上代码可以看到,因为Animal中定义了fly()和swim()方法,所以所有实现它的类都要覆写这两个方法,在Bird类中,鸟会飞,不会游泳,但是又必须要实现swim()方法,Fish类不会飞,但是又必须要实现fly()方法。代码出现冗余。
假如现在又有了新的需求,需要在Animal接口中再增加一个cry()方法,那么之前所有实现了Animal接口的方法势必都在再覆写cry()方法,整个系统中可能会有很多地方需要同步修改,而此时,default方法和静态方法就显得尤为必要了。
改写上面的例子:
Animal.java
public interface Animal {
default void fly() {
System.out.println("birds can fly...");
}
default void swim() {
System.out.println("fishes can swim......");
}
}
Bird.java
public class Bird implements Animal {
}
Fish.java
public class Fish implements Animal {
}
测试类:
public class TestMain {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly();
Fish fish = new Fishe();
fish.swim();
}
}
运行结果:
birds can fly...
fishes can swim......
从修改后代码可以看出,代码得到了复用,Animal实现类中也没有了冗余。
2、静态方法
假如有一个Animal工厂接口,该接口中有一个静态方法create()专门生产不同的Animal,在JDK1.8后由于引入了Lambda表达式,使子类不用覆写该接口的create()方法也可以生产任意的Animal,代码如下:
public interface AnimalFactory {
static Animal create(Supplier<Animal> supplier) {
return supplier.get();
}
}
测试类:
public class TestAnimalFactory {
public static void main(String[] args) {
// 生产一只鸟
Animal bird = AnimalFactory.create(Bird::new);
bird.fly();
// 生产一条鱼
Animal fish = AnimalFactory.create(Fishe::new);
fish.swim();
}
}
运行结果:
birds can fly...
fishes can swim......
3、接口静态方法的“类优先”原则
如果一个接口实现类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略,如改写之前的Bird类:
public class Bird implements Animal {
public void fly() {
System.out.println("Bird类中的fly方法:birds can fly...");
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly();
}
}
运行结果:
Bird类中的fly方法:birds can fly...
可见,调用的是Bird类中自己的fly()方法而不是Animal接口中的默认方法。
4、接口冲突
假如一个类实现了两个接口,两个接口中都有同样的默认方法,哪个是有效的?
答案是:两个都无效!
该类必须要覆该方法来解决冲突,否则编译器将会报错。
Java8新特性之四:接口默认方法和静态方法的更多相关文章
- JDK8新特性之接口默认方法与静态方法
接口默认方法与静态方法 有这样一些场景,如果一个接口要添加一个方法,那所有的接口实现类都要去实现,而某些实现类根本就不需要实现这个方法也要写一个空实现,所以接口默认方法就是为了解决这个问题. 接口静态 ...
- 乐字节-Java8核心特性实战-接口默认方法
JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...
- 【Java8新特性】接口中的默认方法和静态方法,你都掌握了吗?
写在前面 在Java8之前的版本中,接口中只能声明常量和抽象方法,接口的实现类中必须实现接口中所有的抽象方法.而在Java8中,接口中可以声明默认方法和静态方法,本文,我们就一起探讨下接口中的默认方法 ...
- 【Java8新特性】- 接口中默认方法修饰为普通方法
Java8新特性 - 接口中默认方法修饰为普通方法 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学 ...
- Java8新特性_接口中的默认方法
默认方法由来猜想 1. Collection接口.Collections公共类. 同是操作集合,为啥要搞俩?没必要.在接口中搞一些默认实现,一个接口即搞定了. 2. Java8支持Lambda表达式 ...
- java8新特性:接口的默认方法与静态方法
接口中一共可以定义三种方法: 1.抽象方法,也就是需要实现者必须实现的方法,最常见的那种 2.默认方法,不需要实现者实现 3.静态方法,不需要实现者实现 默认方法: 允许在已有的接口中添加新方法,而同 ...
- Java8 新特性 函数式接口
什么是函数式接口 函数式接口是Java8引用的一个新特性,是一种特殊的接口:SAM类型的接口(Single Abstract Method).但是它还是一个接口,只是有些特殊罢了. 函数式接口的 ...
- Java8 新特性----函数式接口,以及和Lambda表达式的关系
这里来讲解一下Java8 新特性中的函数式接口, 以及和Lambda 表达式的关系.看到过很多不少介绍Java8特性的文章,都会介绍到函数式接口和lambda表达式,但是都是分别介绍,没有将两者的关系 ...
- Java8新特性之二:方法引用
上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...
随机推荐
- Quartz学习-- quartz基本介绍和 Cron表达式
Quartz学习 一. Quartz 大致简介 Quartz 是完全由 java 开发的一个开源的任务日程管理系统 任务日程管理系统 换句话说就是: 一个预先确定的日程时间到达时,负责执行任务的 ...
- java实现堆结构
一.前言 之前用java实现堆结构,一直用的优先队列,但是在实际的面试中,可能会要求用数组实现,所以还是用java老老实实的实现一遍堆结构吧. 二.概念 堆,有两种形式,一种是大根堆,另一种是小根堆. ...
- Redis linux 外部telnet访问不通
外部访问不通: 1.修改redis.conf中的daemonize的值设为no: 2.修改redis.conf中的bind的值127.0.0.1为linux本身的ip地址,如192.168.1.120
- android获取手机机型、厂商、deviceID基本信息
/** * 系统工具类 */ public class SystemUtil { /** * 获取当前手机系统语言. * * @return 返回当前系统语言.例如:当前设置的是"中文-中国 ...
- python_集合
>>> import random>>> import time>>> x=list(range(10000))>>> y=se ...
- Coding theano under remote ubuntu server from local Mac (在本地mac机器上,写、跑、调试、看-远程ubuntu上的theano代码)
本人是奇葩,最近鼓捣了一套在mac上coding远程ubuntu上的theano代码的东东,记之以期造福后人. Overview: 下图是我的编程环境和网络环境 我期望能在本地mac机器上对远程的ub ...
- 利用vue-router和compoment重构代码--踩坑(一)
业务主要功能 获取所有的数据库列表 点击某一个数据库列表的时候,右侧分页展示数据 点击右侧某一条数据的时候,现实数据详情 以下是之前的页面,存在以下问题: 前段开发没有工程化(webpack) 主要功 ...
- Spring Cloud Zuul 限流详解(附源码)(转)
在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. ...
- SSM-MyBatis-10:Mybatis中SqlSession的getMapper()和简单的工具类MyBatisUtils
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- getMapper的作用,获取到接口,直接通过点的方式调用方法,以免直接手打的方式写错方法名,(强类型的方式) ...
- 执行指定iframe页面的脚本
mark一下,通过jQuery执行指定iframe页面里面的脚本,当前仅知道页面名称. $(window.top.document).find('iframe[src="pagesrc&qu ...