λ表达式之争:Scala vs Java8
作者:网络转载 发布时间:[ 2015/5/27 13:44:30 ] 推荐标签:编程语言
Lambda对象
Lambda类来继承自scala.runtime.AbstractFunction1。通过这种方式,map() 函数可以多态调用重写后的 apply() 方法,apply()代码如下:
//这段代码是加载this及目标对象,检测它是不是一个字符串,然后调用另一个重载后的、真正工作的apply方法,后包装返回结果
aload_0//加载this
aload_1//加载字符串参数
checkcast java/lang/String//确保是一个字符串 - 得到一个Object
// 调用synthetic类的apply()方法
invokevirtual myLambdas/Lambda1$$anonfun$1/apply(Ljava/lang/String;)I
//包装结果
invokestatic scala/runtime/BoxesRunTime/boxToInteger(I)Ljava/lang/Integer
areturn
真正的执行.length() 操作的代码嵌套在另个一apply方法中,该方法正如我们期望的一样,简单的返回了字符串的长度。
唷……,走了好长的一段路才到这。
aload_1
invokevirtual java/lang/String/length()I
ireturn
我们在上面只是写了一行简单的代码,但是却产生了许多的字节码,包括一个额外的类和一堆方法。但是,这绝不是在劝阻我们不要用Lambda(我们是在Scala中写代码,而不是C)。这仅仅是为了展示这种结构后面的复杂性。
我相当期待Java 8也是用这种方式实现的,但是令人惊讶的时,java采取了完全不同的方式。
Java 8:一种新的方式
Java 8产生的字节码比较短,但是还有更令人惊讶的东西。它刚开始简单的加载了名称变量,然后调用 stream() 方法,但是接下做了一些非常好的优化。它没有创建一个新的对象来包装Lambda函数,而是使用了新的 invokeDynamic 指令,该指令是Java 7时增加的,这个地方的用于调用真实的Lambda函数。
aload_1 // 加载名称变量
//调用stream()方法
invokeinterface java/util/List.stream:()Ljava/util/stream/Stream;
//invokeDynamic指令魔法!
invokedynamic #0:apply:()Ljava/util/function/Function;
//调用map()方法
invokeinterface java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;
InvokeDynamic魔法:这条JVM指令在Java 7中增加,用于减少JVM的限制,允许动态语言在运行时绑定符号。而在这之前,所有的链接都是静态的,在代码编译的时候由JVM完成。
动态链接:如果你看过invokedynamic指令,你会发现没有引用指向真正的Lambda函数(即lambda$0)。答案归结于invokedynamic指令的设计,但是更简短的答案是Lambda表达式的签名,我们的例子来说是
//一个名为lamda$0的函数,获取一个字符串,返回一个整数
lambdas/Lambda1.lambda$0:(Ljava/lang/String;)Ljava/lang/Integer;
存储在.class的一个单独的表中,该表作为#0参数传递给指令。这个新的表确实改变了字节码规范的结构,这是多年之后的第一次改变,这同样需要采取Takipi的错误分析引擎。
Lambda代码
这段代码是真正的Lambda表达式。非常容易,简单地加载字符串参数,调用length()方法并包装成结果。请注意,它是编译成了一个静态函数,避免像之前看到的Scala一样,传入额外的this对象。
aload_0
invokevirtual java/lang/String.length:()
invokestatic java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn
这是invokedynamic方式的另一个优点,它允许我们通过多态的方式来调用 map() 函数,且不需要包装对象或调用虚拟的的重写方法。非常酷!
总结
Java看起非常具有吸引力,“严格”的现代语言现在开始使用动态链接来增加Lambda表达式的功能。该方式也是非常有效的一种方式,不需要加载和编译额外的类,Lambda方法只是我们类中一个简单的私有方法。
Java 8确实对Java 7引入的新的技术做了很多优化,使用了非常直接的方式实现了对Lambda表达式的支持。非常高兴能看到像Java这样“端庄”的女士能教我们一些戏法。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Java性能测试有哪些不为众人所知的原则?Java设计模式??装饰者模式谈谈Java中遍历Map的几种方法Java Web入门必知你需要理解的Java反射机制知识总结编写更好的Java单元测试的7个技巧编程常用的几种时间戳转换(java .net 数据库)适合Java开发者学习的Python入门教程Java webdriver如何获取浏览器新窗口中的元素?Java重写与重载(区别与用途)Java变量的分类与初始化JavaScript有这几种测试分类Java有哪四个核心技术?给 Java开发者的10个大数据工具和框架Java中几个常用设计模式汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等

sales@spasvo.com