在今年(2015)的旧金山的ScalaDays会议上,来自Scala核心团队的Lukas Rytz分享了一个演讲:The JVM Backend and Optimizer in Scala 2.12的技术细节,主要基于Java 8平台上一些改变, 比如Lambda, 缺省方法等。第二部分主要介绍了生成的字节码的优化。
本文是对第一部分做的笔记。
因为2.12还没有正式发布,一下特性可能还无法校验。
函数互操作 (Interop for functions: source and bytecode )
Scala 2.12只能运行在Java 8上。
Scala和Java8实现互操作。
在Scala代码中,可以使用=>
表达式应用在Java Lambda表达式的位置。
1 2
| new Thread(() => println("running")).start
|
在Java代码中,可以使用Lamabda表达式作为函数对象应用在=>
表达式的位置:
1 2
| scalaCollection.foreach(x-> println(x))
|
这样Scala和Java Lambda表达式实现了互操作。
之所以能这样替换,是因为Scala 2.12将lambda表达式编译的字节码和Java的字节码是一致的,而不是匿名函数的方式。
因此在Scala代码中,函数式接口(Functional interfaces,也叫SAM)都可以通过Scala的 =>
实现。
在看一个Java Stream中使用函数式接口SAM的例子:
1 2 3 4 5
| stream.filter(s -> s.startsWith("c")) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
|
在Scala中代码中我们使用=>
实现这些SAM:
1 2 3 4 5 6 7
| import java.util.stream.Stream var s = Stream of ("a1","a2","b1","c2","c1") s.filter(s => s.startsWith("c")) .map(_.toUpperCase).sorted.forEach(println)
|
毫无违和感。
Java中使用Scala类库时遇到SAM时:
在Scala 2.12中, FunctionN是函数式接口:
1 2
| scalaCollection.foreach(x -> println(x));
|
在Scala 2.11中,要使用兼容包,JFunctionN是函数式接口。
1 2 3
| import static scala.compat.java8.JFunction.*; scalaCollection.foreach(func(x -> println(x)));
|
编译Trait时使用缺省方法 (Make use of default methods )
比如下面一个trait:
1 2 3 4
| trait F1 { def apply def add(x:Int, y:Int) = x+y }
|
会被编译成两个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public abstract interface F1 { public abstract void apply(); public abstract int add(int paramInt1, int paramInt2); } public abstract class F1$class { public static int add(F1 $this, int x, int y) { return x + y; } public static void $init$(F1 $this) { } }
|
有几种方案来编译成SAM。一种就是
1 2 3 4 5 6 7 8
| public interface F1 { public abstract void apply(); public default int add(int paramInt1, int paramInt2) { return F1$class.add(paramInt1, paramInt2) } }
|
或者直接编译成SAM,不需要一个辅助类F1$class
。
可以关注Scala 2.12正式发布后的实现方式。