#Java学了这么久,项目也做了?基础知识还不巩固?快来关注我的这篇系列博客——Java基础复习巩固吧#
目录
引言
一、JDK8新特性:允许在接口中定义非抽象方法和静态方法。
注意事项
二、JDK9新特性:允许在接口中定义private私有方法。
引言
Java中的接口起到了规范项目业务逻辑的作用,在JDK8以前,接口中的方法默认是抽象的,即只有方法的声明,没有方法的实现。
- 从 JDK 8 开始,接口中可以定义非抽象方法和静态方法。
- 从 JDK 9 开始,接口中可以定义私有方法和静态私有方法。
那么,Java设计师们为何要对借口进行这一系列的改进呢?下面请让我来为大家解答。
一、JDK8新特性:允许在接口中定义非抽象方法和静态方法。
新增特性:
- 允许在接口中定义非抽象方法,但需要使用default关键字修饰,称为接口的默认方法;
- 允许在借口中定义非抽象的静态方法
目的:解决接口升级的问题;
例如,当团队的第一版项目成功上线,一段时间要对项目进行全面升级,要求丰富某一个接口的功能,新增8个方法;假如该项目中有100个类都实现了该接口,那么借口一旦改动,这100个类的都要重写新增方法,牵一发而动全身 。
为了解决这个普遍问题,JDK8中允许接口中定义非抽象方法(通常称默认方法),实现该接口的类不用对默认方法进行重写而是可以直接继承,这极大减小了项目中升级接口的代价。
接口中默认方法的定义格式:
○格式: public default 返回值类型 方法名(参数列表){}
○范例: public default void show ( ) {....}
代码示例:
//定义一个接口
interface interA{
void func01(); //抽象方法func1
default void method(){
System.out.println("我是接口中的默认方法method...");
}
}
//定义一个类A,实现接口interA
class A implements interA{
@Override
public void func01() {
System.out.println("我是方法func01,我被重写了...");
}
}
//定义一个类B,实现接口interA
class B implements interA{
@Override
public void func01() {
System.out.println("我是方法func01,我被重写了...");
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
a.method();
}
}
输出:我是接口中的默认方法method...
上述代码中,接口interA中有一个抽象方法func01()和一个默认方法method(),实现该接口的类A和类B必须重写接口中的func01()而无需重写默认方法method();而是直接继承了接口中的默认方法;类A的示例a可以直接调用默认方法method()
此时的你可能会提出一个疑问:如果一个类实现了多个接口,而这些接口中存在相同名字的默认方法时,那么这个类到底继承的是那个接口中(方法名相同)的默认方法呢?
答案就是,编译器会先报错,提示你必须重写这个多个接口中(方法名相同)的默认方法。
//定义两个接口interA和interB
interface interA{
void funcA(); //抽象方法func1
default void method(){
System.out.println("我是接口A中的默认方法method...");
}
}
interface interB{
void funcB();
default void method(){
System.out.println("我是接口B中的默认方法method...");
}
}
//定义一个类A,实现接口interA和interB
class A implements interA,interB{ //会报错
@Override
public void funcA() {
System.out.println("我是方法funcA,我被重写了...");
}
@Override
public void funcB() {
System.out.println("我是方法funB,我被重写了...");
}
}
此时类A上会报错,如下图:
test.A inherits unrelated defaults for method() from types test.interA and test.interB(类A从类型test.interA和test.interB继承了method()的不相关默认值)
重写method()方法就好了:
那么既然JDK8都允许了接口中可以定义非抽象方法,在开放一点也无妨,随后静态方法也允许在接口中存在。且只能通过接口名来调用
代码格式如下:
//定义一个接口inter
interface inter {
//在该接口中定义一个静态方法func()
public static void func(){
System.out.println("我是接口中的静态方法func");
}
}
用借口名来调用接口中的静态方法:
public class Test {
public static void main(String[] args) {
inter.func();
}
}
输出:我是接口中的静态方法func
注意事项:
1.接口中的默认方法:
- 接口中的所有方法默认都是公有的,因此public可以省略,但default不能省略。
- 接口的实现类允许重写接口中的默认方法,重写时要去掉default关键字。
- 如果某个类实现了多个接口,且这多个接口中存在相同的默认方法,则实现类必须重写这个默认方法
2.接口中的静态方法:
- 关键字public可以省略,但static不能省略。
- 接口中的静态方法,只允许通过接口名进行调用,不允许该接口实现类的对象调用
二、JDK9新特性:允许在接口中定义private私有方法。
初学者小伙伴你是否有疑问?接口中的私有方法,实现类无法继承,也无法使用,有啥意义啊?
下面请看一个例子:
//定义一个接口inter
interface inter {
//在该接口有多个默认方法,且都有相同的代码部分
default void start(){
System.out.println("执行start方法....");
System.out.println("请求资源");
System.out.println("更新日志");
System.out.println("保存日志");
}
default void login(){
System.out.println("执行login方法....");
System.out.println("请求资源");
System.out.println("更新日志");
System.out.println("保存日志");
}
default void end(){
System.out.println("执行end方法....");
System.out.println("请求资源");
System.out.println("更新日志");
System.out.println("保存日志");
}
}
由于接口中可以定义非抽象方法了,那么就有可能有重复的代码逻辑,上述代码有大量的重复内容,若通过编写一个默认方法来封装并代替这些重复代码,那么这个多写的默认方法就会被接口的实现类继承(一个无实际业务逻辑的方法不应当被继承),当有了私有方法后,就可以借助私有方法:
interface inter {
//在该接口有多个默认方法
default void start(){
System.out.println("执行start方法....");
log();
}
default void login(){
System.out.println("执行login方法....");
log();
}
default void end(){
System.out.println("执行end方法....");
log();
}
private void log(){
System.out.println("请求资源");
System.out.println("更新日志");
System.out.println("保存日志");
}
}
此时借用私有方法来封装这些重复的代码逻辑,来减少代码量;确保这些重复的代码逻辑不被实现类继承,并且实现代码的复用。
作用:提升代复用性,减少冗余代码