Java8中的 Default 方法
2016-02-29 23:06
363 查看
第二章 Default 方法
为什么要有Default方法
在Java8发布之际,有件事情就显得非常重要,即在不破坏java现有实现架构的情况下能往接口里增加新方法。引入Default方法到Java8,正是为了这个目的:优化接口的同时,避免跟现有实现架构的兼容问题。看下面例子:List<?> list = ... list.forEach(...);// Lambda code goes here |
这样,即使我们把Lambda表达式引入到java8中,但是因为不能牺牲向后兼容,而不可以把Lambda表达式和标准集合类库结合使用的话,会真的让人很泄气。
为了解决上述问题,引入了一个新的概念,即虚拟扩展方法(Virtual extension methods),通常也称之为 defender 方法,它目前可以添加到接口中,为声明的方法提供默认的实现。
简单地说,Java接口现在可以有非抽象方法了。Default 方法带来的好处是,往接口新增一个Default 方法,而不破坏现有的实现架构。
尽管如此,Default 方法不适合过多使用,但是对于Java集合API的优化升级,并达到无缝地结合Lambda表达式来说,Default 方法是至关重要的特性。
Default方法入门
让我们从最简单可行的例子开始:下面代码定义了接口A,以及实现了接口A的Clazz类:public interface A { default void foo(){ System.out.println("Calling A.foo()"); } } public class Clazz implements A {} |
上例的客户端代码如下:
Clazz clazz= new Clazz(); clazz.foo();// Calling A.foo() |
让我们用上一个例子来解释上述情况,代码如下所示:
public interface A { default void foo(){ System.out.println("Calling A.foo()"); } } public interface B { default void foo(){ System.out.println("Calling B.foo()"); } } publicclassClazzimplements A, B {} |
java: class Clazz inherits unrelated defaults for foo() from types A and B
为了修复错误,在Clazz中,我们手工地覆写掉冲突的方法来处理这个问题,如下所示:
public class Clazz implements A, B { public void foo(){} } |
public class Clazz implements A, B { public void foo(){ A.super.foo(); } } |
@FunctionalInterface public interface Iterable{ Iterator iterator(); default void forEach(Consumer<?super T> action){ Objects.requireNonNull(action); for(T t: this){ action.accept(t); } } } |
List<?> list = ... list.forEach(System.out::println); |
方法调用
我们来看看实际上是如何调用default方法的。从客户端代码角度来看,default方法只不过都是初始化的抽象方法。因此default方法也叫-虚拟扩展方法。如果出现上例中的那个类,该类实现了带default方法的接口,那么调用default方法的客户端代码会在调用端生成invokeinterface 。如下所示
A clazz= new Clazz(); clazz.foo();// invokeinterface foo() Clazz clazz= new Clazz(); clazz.foo();// invokevirtual foo() |
public class Clazz implements A, B { public void foo(){ A.super.foo();// invokespecial foo() } } |
public void foo();
Code:
0: aload_0
1: invokespecial #2 // InterfaceMethodA.foo:()V
4: return
如上面所示的,invokespecial 指令用来调用接口中定义的方法foo()。这从字节码的角度看也是新东西,因为先前你进行方法调用,仅是通过指向父类的super而不是指向父接口的。
总结
Default方法加入到java中,这是引人关注的事情。Default方法可以认为是Lambda表达式和JDK类库之间的桥梁。引入Default方法的主要目的是为了升级标准JDK接口,另外也是为了我们最终能在Java8中顺畅使用Lambda表达式。相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树