gpt4 book ai didi

scala - Scala 闭包如何转换为 Java 对象?

转载 作者:行者123 更新时间:2023-12-03 13:23:08 25 4
gpt4 key购买 nike

我目前正在研究不同语言的闭包实现。然而,当谈到 Scala 时,我找不到任何关于如何将闭包映射到 Java 对象的文档。

Scala 函数映射到 FunctionN 对象是有据可查的。我假设对闭包的自由变量的引用必须存储在该函数对象的某个位置(就像在 C++0x 中所做的那样,例如)。

我还尝试使用 scalac 编译以下内容,然后使用 JD 反编译类文件:

object ClosureExample extends Application { 
def addN(n: Int) = (a: Int) => a + n
var add5 = addN(5)
println(add5(20))
}

在反编译的源代码中,我看到了 Function1 的匿名子类型,它应该是我的闭包。但是 apply() 方法是空的,并且匿名类没有字段(可能存储闭包变量)。我想反编译器没有设法从类文件中得到有趣的部分......

现在的问题:
  • 你知道转换是如何完成的吗?
  • 你知道它记录在哪里吗?
  • 你有其他想法我可以如何解开这个谜吗?
  • 最佳答案

    让我们分解一组示例,以便我们了解它们的不同之处。 (如果使用 RC1,请使用 -no-specialization 进行编译以使事情更容易理解。)

    class Close {
    var n = 5
    def method(i: Int) = i+n
    def function = (i: Int) => i+5
    def closure = (i: Int) => i+n
    def mixed(m: Int) = (i: Int) => i+m
    }

    首先,让我们看看 method做:
    public int method(int);
    Code:
    0: iload_1
    1: aload_0
    2: invokevirtual #17; //Method n:()I
    5: iadd
    6: ireturn

    很简单。这是一种方法。加载参数,调用 n 的 getter ,添加,返回。看起来就像Java。
    function 怎么样?它实际上并没有关闭任何数据,但它是一个匿名函数(称为 Close$$anonfun$function$1 )。如果我们忽略任何特化,构造函数和应用是最感兴趣的:
    public scala.Function1 function();
    Code:
    0: new #34; //class Close$$anonfun$function$1
    3: dup
    4: aload_0
    5: invokespecial #35; //Method Close$$anonfun$function$1."<init>":(LClose;)V
    8: areturn

    public Close$$anonfun$function$1(Close);
    Code:
    0: aload_0
    1: invokespecial #43; //Method scala/runtime/AbstractFunction1."<init>":()V
    4: return

    public final java.lang.Object apply(java.lang.Object);
    Code:
    0: aload_0
    1: aload_1
    2: invokestatic #26; //Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
    5: invokevirtual #28; //Method apply:(I)I
    8: invokestatic #32; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
    11: areturn

    public final int apply(int);
    Code:
    0: iload_1
    1: iconst_5
    2: iadd
    3: ireturn

    因此,您加载一个“this”指针并创建一个以封闭类作为其参数的新对象。这是任何内部类(Class)的标准,真的。该函数不需要对外部类做任何事情,所以它只调用 super 的构造函数。然后,在调用 apply 时,您执行 box/unbox 技巧,然后调用实际的数学运算——也就是说,只需添加 5。

    但是如果我们在 Close 中使用变量的闭包呢?设置完全一样,但现在构造函数 Close$$anonfun$closure$1看起来像这样:
    public Close$$anonfun$closure$1(Close);
    Code:
    0: aload_1
    1: ifnonnull 12
    4: new #48; //class java/lang/NullPointerException
    7: dup
    8: invokespecial #50; //Method java/lang/NullPointerException."<init>":()V
    11: athrow
    12: aload_0
    13: aload_1
    14: putfield #18; //Field $outer:LClose;
    17: aload_0
    18: invokespecial #53; //Method scala/runtime/AbstractFunction1."<init>":()V
    21: return

    也就是说,它检查以确保输入是非空的(即外部类是非空的)并将其保存在一个字段中。现在到了应用它的时候,在装箱/拆箱包装器之后:
    public final int apply(int);
    Code:
    0: iload_1
    1: aload_0
    2: getfield #18; //Field $outer:LClose;
    5: invokevirtual #24; //Method Close.n:()I
    8: iadd
    9: ireturn

    您会看到它使用该字段来引用父类,并为 n 调用 getter .添加,返回,完成。因此,闭包很简单:匿名函数构造函数只是将封闭类保存在私有(private)字段中。

    现在,如果我们关闭的不是内部变量,而是方法参数呢?就是这样 Close$$anonfun$mixed$1做。先看看 mixed是什么方法做:
    public scala.Function1 mixed(int);
    Code:
    0: new #39; //class Close$$anonfun$mixed$1
    3: dup
    4: aload_0
    5: iload_1
    6: invokespecial #42; //Method Close$$anonfun$mixed$1."<init>":(LClose;I)V
    9: areturn

    它加载参数 m在调用构造函数之前!所以构造函数看起来是这样的也就不足为奇了:
    public Close$$anonfun$mixed$1(Close, int);
    Code:
    0: aload_0
    1: iload_2
    2: putfield #18; //Field m$1:I
    5: aload_0
    6: invokespecial #43; //Method scala/runtime/AbstractFunction1."<init>":()V
    9: return

    该参数保存在私有(private)字段中。没有保留对外部类的引用,因为我们不需要它。你也不应该对 apply 感到惊讶:
    public final int apply(int);
    Code:
    0: iload_1
    1: aload_0
    2: getfield #18; //Field m$1:I
    5: iadd
    6: ireturn

    是的,我们只需加载该存储字段并进行数学运算。

    我不确定你在做什么而不是在你的例子中看到这一点——对象有点棘手,因为它们都有 MyObjectMyObject$类和方法以一种可能不直观的方式在两者之间进行拆分。但是 apply 肯定会应用事物,总体而言,整个系统几乎按照您期望的方式运行(在您坐下来认真思考很长时间之后)。

    关于scala - Scala 闭包如何转换为 Java 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2670350/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com