没有合适的资源?快使用搜索试试~ 我知道了~
λ表达式之争:Scala vs Java8
需积分: 0 0 下载量 167 浏览量
2020-12-22
17:00:17
上传
评论
收藏 98KB PDF 举报
温馨提示
试读
2页
近几年Lambda表达式风靡于编程界。很多现代编程语言都把它作为函数式编程的基本组成部分。基于JVM的编程语言如Scala、Groovy及Clojure把它作为关键部分集成在语言中。而如今,(终)Java 8也加入了这个有趣的行列。 Lambda表达式有意思的地方在于,在JVM的角度来看它是完全不可见的。在JVM中没有匿名函数或Lambda表达式的概念。JVM知道是字节码。字节码是一个严格的OO规范。由语言的创造者和编译者通过这些限制来创建新的、高级的语言元素。 我们第一次遇到Lambda表达式是需要在Takipi中增加对Scala的支持,所以不得不深入了解Scala的编译器。而这
资源详情
资源评论
资源推荐
λ表达式之争:表达式之争:Scala vs Java8
近几年Lambda表达式风靡于编程界。很多现代编程语言都把它作为函数式编程的基本组成部分。基于JVM的编程语言如
Scala、Groovy及Clojure把它作为关键部分集成在语言中。而如今,(终)Java 8也加入了这个有趣的行列。
Lambda表达式有意思的地方在于,在JVM的角度来看它是完全不可见的。在JVM中没有匿名函数或Lambda表达式的概
念。JVM知道是字节码。字节码是一个严格的OO规范。由语言的创造者和编译者通过这些限制来创建新的、高级的语言元
素。
我们第一次遇到Lambda表达式是需要在Takipi中增加对Scala的支持,所以不得不深入了解Scala的编译器。而这时Java
8也正处在关键时刻。我猜想Scala和Java编译器对Lambda表达式的实现肯定会非常有趣。结果让我极为惊讶。
为了演示这些内容,我写了一个简单的Lambda表达式,功能是将一个字符串列表转换为它们长度的列表。
Java:
List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());
Scala:
val names = List("1", "2", "3")
val lengths = names.map(name => name.length)
不要被它表面的简单所迷惑,后面执行了相当复杂的过程。
我们从Scala开始
代码
我使用 javap 来查看通过Scala编译器生成的.class文件的字节码的内容。让我们看一下字节码的结果(这才是JVM真正执
行的内容)。
//将变量名加载到栈中(JVM视为变量#2),先保存在这,之后会在map函数中用到
aload_2
接下来的事情变得更有趣了,一个由编译器生成的synthetic的实例创建并初始化(译者注:Synthetic类是指由JVM运行
时生成的类)。非常有意思的是,Lambda作为整个方法的一部分来定义的,但它实际上完全存在于我们类的外部。
new myLambdas/Lambda1$$anonfun$1 //实例化Lambda对象
dup //把它加入栈中
//后,调用构造函数.记住,这是源自JVM的一个简单对象
invokespecial myLambdas/Lambda1$$anonfun$1/()V
//这个两行加载immutable.List CanBuildFrom工厂,该工厂能生成新的list。工厂模式是Scala的集合架构的一部分。
getstatic scala/collection/immutable/List$/MODULE$
Lscala/collection/immutable/List$;
invokevirtual scala/collection/immutable/List$/canBuildFrom()
Lscala/collection/generic/CanBuildFrom;
//现在,栈上已经有了Lambda对象及工厂,下一阶段可以调用map函数。
//你应该还记得,我们在一开始的时候将名称变量加载到了栈中。我们现在可以用它来实现map方法的调用了。
//map方法接受一个Lambda对象和一个工厂,生成一个长度的list。
invokevirtual scala/collection/immutable/List/map(Lscala/Function1;
Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
但是请稍等,Lambda对象内部做了什么事情?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
//包装结果
weixin_38631729
- 粉丝: 8
- 资源: 905
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0