default关键字的用法
default关键字的用法
前言
在学习集合时,深入到Iterable发现了这个default关键字
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
理论探究
default关键字在java中,目前有两个地方能用到
一是switch中的default:switch在匹配时,最后来一个default,防止因为没有匹配到结果,使后续程序异常。
二是接口中的default:从JDK8开始,接口中可以添加默认方法了,default就是用来修饰这个方法的。
代码实现
switch中的default
switch执行过程中,如果没有符合条件的case,就执行default下的代码块,这里的default并不是必要的,也可以不写,程序也会正常执行,只是,如果后续有业务用到这个switch的值,而代码中又没有匹配到相关结果,可能就会出问题。
package com.cdh.keyDefault;
/**
* @author chudonghai
* @ClassName SwitchDefaultDemo
* @Description switch中的default
*/
public class SwitchDefaultDemo {
public static void main(String[] args) {
defaultTest();
}
/*
* 判断是否匹配:不匹配
* 输出:ERROR!
*/
private static void defaultTest() {
String string = new String("helloworld");
switch (string) {
case "hello":
System.out.println("hello case");
break;
case "world":
System.out.println("world case");
break;
default:
System.out.println("ERROR!");
break;
}
}
}
接口中的default
重点来了,这是本篇的重头戏,这也是JDK8加入的新特性。
接口有很多的好处,诸如多实现,低耦合,对外提供规则等;
但缺点也会在某些场景中凸显出来,当修改接口时,需要修改全部实现该接口的类。
例如:JDK8,在Iterable中,新增了一个新方法forEach
,这里就出现一个问题。
目前,JDK8之前的版本,集合框架都没有foreach方法,如何对已发布的接口进行修改而又不影响当前实现类的正常运行,这在生产中是一个很大的问题。对此,我们一般能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,无法同时满足既给接口添加新方法又不影响已有的实现,如果一味强行在每个类中进行添加,且不说风险问题,单是这个工作量就足以让程序员们彻夜不休,如果项目庞大,这个工作量更是让人生畏,所以,之前都是尽量避免这种改接口的问题。为此JDK8引入了默认方法default。它同时满足了既给接口添加新方法又不影响已有的实现这个大难题。
好了扯了这一堆希望你能听懂,不懂也没关系,咱看看代码:
接口中default的用法(代码实现)
1.直接调用父接口实现
/**
* @author chudonghai
* @InterfaceName Interface1
* @Description 创建接口Interface1,并在接口中定义默认方法helloworld
*/
public interface Interface1 {
default void helloworld() {
System.out.println("this is JDK8 Interface1");
}
}
/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1{
public static void main(String[] args) {
MyImpl1 mi = new MyImpl1();
mi.helloworld();
}
}
此时,接口-类关系图,如下:
结果如下:
this is JDK8 Interface1
2.继承多个接口
/**
* @author chudonghai
* @ClassName Interface2
* @Description 创建接口Interface2,并在接口中定义默认方法helloworld
*/
public interface Interface2 {
default void helloworld() {
System.out.println("this is JDK8 Interface2");
}
}
/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1,接口2的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1,Interface2{
public static void main(String[] args) {
MyImpl1 mi = new MyImpl1();
mi.helloworld();
}
}
此时发现实现类MyImpl1会报错:Duplicate default methods named helloworld...
翻译过来就是,名为helloworld的默认方法重复啦,,,
也就是说,现在程序不知道你到底是要运行哪个接口中的helloworld方法,怎么办???
下面提供两种解决办法:
方法一:直接指定这个方法属于哪个接口。
方法二:直接进行重写此方法。
/**
* @author chudonghai
* @ClassName MyImpl1
* @Description MyImpl1:接口1,接口2的实现类,调用接口中的默认方法
*/
public class MyImpl1 implements Interface1,Interface2{
public static void main(String[] args) {
MyImpl1 mi = new MyImpl1();
mi.helloworld();
}
// /**
// * 方法一:直接指定这个方法属于哪个接口
// * */
// @Override
// public void helloworld() {
// Interface1.super.helloworld();
// }
/**
* 方法二:直接重写此方法
* */
@Override
public void helloworld() {
System.out.println("Here is MyImpl1");
}
}
此时,接口-类关系图,如下:
方法一结果如下:
this is JDK8 Interface1
方法二结果如下:
Here is MyImpl1
3.类优先于接口
/**
* @author chudonghai
* @ClassName MyImpl2
* @Description MyImpl2继承MyImpl1(方法helloworld已重写)实现Interface2
*/
public class MyImpl2 extends MyImpl1 implements Interface2{
/**
* 此时,MyImpl2中调用的helloWorld到底是MyImpl1中的还是Interface2中的?
* 答案:是MyImpl1中的
* 原因:类优先于接口。从结果来看确是如此
* */
public static void main(String[] args) {
MyImpl2 mi = new MyImpl2();
mi.helloworld();
}
}
此时,接口-类关系图,如下:
结果如下:
Here is MyImpl1
总结
default的使用场景:
- switch中的default:switch在匹配时,最后添加default,防止因为没有匹配到结果,使后续程序异常。
- 接口中的default:从JDK8开始,接口中可以添加默认方法了,default就是用来修饰这个方法的。
①直接调用父接口实现
②继承多个接口
③类优先于接口
=======================================================================================
善于学习,善于总结
=======================================================================================