浅析Java8中default关键字
摘要:介绍Java8新增关键字default,它用于在接口中标记方法为默认方法和编写实现逻辑,方便通过新增方法重构接口,而无需修改所有实现类,目的在于兼容接口已有实现类。
综述
default关键字:是在java 8中引入的新概念,也可称为Virtual extension methods——虚拟扩展方法与public、private等都属于修饰符关键字,与其它两个关键字不同之处在于default关键字大部分都用于修饰接口。default修饰方法时只能在接口类中使用,在接口中被default标记的方法可以直接写方法体,而无需修改所有实现了此接口的类。
这打破了Java之前版本对接口的语法限制。之前的版本里 interface 中的方法必须是抽象方法,不能有方法体。现在可以添加 interface 内方法,只需要在方法的前面加一个 default 关键字,表示属于接口内部默认存在的方法,但是,实现类中可以重写其实现,也可以不重写。在调用default修饰的方法时,如果没有匹配的实现类实现它,就执行接口类中定义的默认实现逻辑;否则,执行实现类中的逻辑。
default的前世今生
之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改该接口的全部实现类。例如,java8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进了默认方法。他们的目的是为了解决实现接口的缺陷问题(就是如果想修改接口时,所有实现了该接口的类都需要去修改)。
通俗地讲,不使用default定义方法的话,该interface的实现类都必须重写所有的抽象方法,但是,在实现含有default方法的接口时,可以直接使用接口的default方法,也可以在个别实现类中重写接口中的default方法从而实现自己的业务逻辑。
如何使用default关键词
实现类会继承接口中的default方法。创建一个person类, 使用default修饰该方法:
public interface Person {
default String getName(){
return "我是默认姓名";
}
default String getId(){
return "我是默认ID";
}
}
实现该接口的类不需要去实现默认方法,也可以实现,我们实现其中的一个,看看效果:
@Service
public class Student implements Person {
@Override
public String getId() {
return "32";
}
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getName());
System.out.println("重写接口类的默认方法,则结果由实现类决定:");
System.out.println(student.getId());
}
}
执行main方法进行验证,运行结果如下:
我是默认姓名
重写接口类的默认方法,则结果由实现类决定:
32
总而言之,当我们修改interface类的代码添加新功能时,必须要想尽办法兼容历史版本的代码,更何况这还是伟大的java,default方法应运而生。
解决冲突
如果集成的两个接口有default定义的同一个方法,例如
public interface Person1 {
default String getName(){
return "我是另一个默认姓名";
}
}
则编译器会报错。发生这种情况的原因是,实现类MyImplement即实现了接口Person又实现了接口Person1,恰巧两个接口中都定义可相同的默认方法。说白了就是编译器此时已经被干懵了,当我们在实现类Student中调用方法时,它不知道该去调用哪个接口类的默认方法。解决方法就是在实现类中实现该方法,重写接口实现。为什么要重写方法呢?是因为类在继承接口中的default方法时,不知道应该继承哪一个接口中的default方法。修改Student类后,代码如下:
@Service
public class Student implements Person, Person1 {
@Override
public String getName() {
return "我是实现类中定义的姓名";
}
@Override
public String getId() {
return "32";
}
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getName());
System.out.println("重写接口类的默认方法,则结果由实现类决定:");
System.out.println(student.getId());
}
}
类优先于接口
创建一个实现类Student1,该实现类不仅继承了Student而且实现了Person1。
public class Student1 extends Student implements Person1 {
public static void main(String[] args) {
Student1 student = new Student1();
System.out.println(student.getName());
}
}
问题:在实现类Student1中调用 getName() 方法,到底执行的是Student还是Person1中的方法?
答:因为类优先于接口,所以将会执行Student中的方法。
结束语
本文介绍Java8新增关键字default,它用于在接口中标记方法为默认方法和编写方法体,方便通过新增方法重构接口,而无需修改所有实现类,目的在于兼容接口已有实现类。同时,演示了类优先于接口的规则。
大家如果对于本文介绍的内容有不理解的地方,请在评论区留言。如果碰到【相关】问题也可以在评论区留言,和诸位互动交流。三人行必有我师,一起进步。大家可随意尽情享用本文啦!
Reference
浅析Java8中default关键字的更多相关文章
- C# 7.1中default关键字的新用法
default 关键字有两类用法 switch语句中指定默认标签 默认值表达式 switch 语句 int caseSwitch = 1; switch (caseSwitch) { case 1: ...
- 浅析c++中virtual关键字
http://blog.csdn.net/djh512/article/details/8973606 1.virtual关键字主要是什么作用? c++中的函数调用默认不适用动态绑定.要触发动态绑定, ...
- C#中default 、base 、this关键字用法简介
C#中default关键字用法简介 default 关键字可在switch语句或泛型代码中使用.switch语句:指定默认标签.泛型代码:指定类型参数的默认值.对于引用类型为空,对于值类型为零swi ...
- 浅析Java中的final关键字
浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- Java8中的default方法
default方法 Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods). Default方 ...
- [转载]浅析Java中的final关键字
浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- default 关键字泛型代码中的默认关键字(C# 编程指南)
在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T: T 是引用类型还是值类型. 如果 T 为值类型,则它是数值还是结构. 给定参数化类型 T 的一个变量 t ...
- 【转】浅析Java中的final关键字
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...
- C#default关键字(泛型代码中的默认关键字)
在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T:T 是引用类型还是值类型.如果 T 为值类型,则它是数值还是结构.给定参数化类型 T 的一个变量 t,只有 ...
- Java8 中的 default
之前的版本里 interface 中的方法必须是抽象方法,不能有方法体.现在可以添加 interface 内方法,只需要在方法的前面加一个 default 关键字,表示属于接口内部默认存在的方法. 如 ...
随机推荐
- manim边学边做--场景Scene简介
在 Manim 社区版本中,Scene(场景)是构建动画的核心概念之一,它为我们提供了一个结构化的方式来组织和呈现动画内容. 本文将介绍什么是Scene,它在Manim动画中的作用,以及不同类型的Sc ...
- 【Python】函数传参的方式
学习笔记//20230402 edit 1.传参类型 值传递 引用传递 就像C++的参数传递: 值传递时值把实参的值传递给function, function 内对形参的修改不会影响实参; 引用传递时 ...
- Vue3状态管理终极指南:Pinia保姆级教程
一.为什么选择Pinia?(Vuex对比分析) 1.1 核心优势解析 Composition API优先 :天然支持Vue3新特性,代码组织更灵活 TypeScript友好 :内置类型推导,无需额外类 ...
- 通过 C# 打印Word文档
Word文档是日常办公和学习中不可或缺的一部分.比如在商务往来中,经常需要打印 Word 文档用于撰写和传递正式的商务信函.合作协议.项目提案等.打印出来的文档便于双方签字盖章,具有法律效力和正式性. ...
- k8s 报错: node(s) didn't match Pod's node affinity.
前言 k8s集群中,有pod出现了 Affinity ,使用 kubectl describe pod 命令,发现了报错 2 node(s) didn't match Pod's node affin ...
- 入口函数与包初始化:Go程序的执行次序
前言 我们可能经常会遇到这样一个问题:一个 Go 项目中有数十个 Go 包,每个包中又有若干常量.变量.各种函数和方法,那 Go 代码究竟是从哪里开始执行的呢?后续的执行顺序又是什么样的呢? 事实上, ...
- 【VMware VCF】解决 VCF 环境中组件用户密码过期问题。
由于长时间没有启动 VCF 环境,现在在启动 SDDC Manager 组件后,UI 一直处于如下图所示的"初始化"状态.当时第一直觉就认为肯定是 VCF 环境组件的用户密码过期了 ...
- Docker容器详解
[] 容器(Container)是一种轻量级的虚拟化技术,它通过操作系统级的虚拟化,将应用程序及其依赖环境打包在一起,确保应用程序可以在任何环境中一致运行.与虚拟机不同,容器共享宿主操作系统的内核,而 ...
- Delphi编写的一款锁屏小工具
Delphi编写的一款锁屏小工具,双击程序立即锁屏,木有界面的.解除锁屏密码:alt+空格. unit Unit1; interface uses Windows, Messages, SysUtil ...
- .NET 生成PDF文件
1.网上检索N种解决方案 QuestPDF:简单方便实用,文档也相对来说全,但是开源协议,当企业规模大的100W美金需要收费,未来存在潜在版权问题. itext7:感觉实用偏复杂,项目类库引用复杂,不 ...