要查看函数字面量,请使用
:javap -fun
:
$ scala
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_51).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def f = (1 to 10) map (_ * 2)
f: scala.collection.immutable.IndexedSeq[Int]
scala> :javap -fun f
Compiled from "<console>"
public final class $anonfun$f$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable {
public static final long serialVersionUID;
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
public $anonfun$f$1();
}
这是传递给map函数的匿名函数。
要过滤应用方法(即函数体),请使用尾随的#
或f#apply
:
scala> :javap -fun f#
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
那包括专业的方法。
scala> :javap -fun -prv f
public final int apply(int);
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual
5: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 6 1 x$1 I
LineNumberTable:
line 10: 0
public int apply$mcII$sp(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: iconst_2
2: imul
3: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 4 1 x$1 I
LineNumberTable:
line 10: 0
public final java.lang.Object apply(java.lang.Object);
flags: ACC_PUBLIC, ACC_FINAL, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokestatic
5: invokevirtual
8: invokestatic
11: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 12 1 v1 Ljava/lang/Object;
LineNumberTable:
line 10: 0
scala>
对于vals,首先查看评估的构造函数:
scala> :javap -fun c
Failed: No closures found.
scala> :javap -prv c
[snip]
public $line7.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
0: aload_0
1: invokespecial #20
4: aload_0
5: putstatic #22
8: aload_0
9: getstatic #27
12: invokevirtual #30
15: new #32
18: dup
19: invokespecial #33
22: invokeinterface #39, 2
[snip]
然后剪切/粘贴anonfun的名称,可选择添加#
以仅筛选应用方法:
scala> :javap -prv $line7/$read$$iw$$iw$$anonfun$1#
public final boolean apply(int);
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual
5: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this L$line7/$read$$iw$$iw$$anonfun$1;
0 6 1 x I
LineNumberTable:
line 12: 0
public boolean apply$mcZI$sp(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: iconst_2
2: irem
3: iconst_0
4: if_icmpne 11
7: iconst_1
8: goto 12
11: iconst_0
12: ireturn
[snip]
存储在
c
中的函数:
scala> $intp.isettings.unwrapStrings = false
$intp.isettings.unwrapStrings: Boolean = false
scala> c.getClass
res4: Class[_ <: Int => Boolean] = class $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
scala> :javap -prv $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
[snip]
-raw
选项用于
:javap
,可以显示REPL的包和封装对象。如果要在普通输出中看到它们,您需要关闭输出过滤,如下所示。
或者:
scala> $intp.withoutUnwrapping(println(c.getClass))
class $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
通常匿名函数很简短,因此不需要过滤应用程序方法。
请注意,我已经将这个功能剥离出来,转换为Java 8 lambda后,因为编码一直在变化。也许有朝一日它会被恢复。
javap
在这里真的没有帮助,因为b
返回的每个函数都有相同的代码。 返回的函数之间的区别仅在于它们关闭了不同的f
值。(你的问题,特别是你对“生成”一词的使用,让我想知道你是否正在设想一个不同的基础机制。) - Seth Tisue