gpt4 book ai didi

Scala 对象初始化

转载 作者:行者123 更新时间:2023-12-03 22:37:34 26 4
gpt4 key购买 nike

我有一个对象:

object A {
val init = println("Hello")
}

我在一个特征中使用它:
trait SomeTratit {
val a = A.init
}

然后我在一个类中使用 trait it:
class SomeClass extends SomeTrait

当我用 new SomeClass 实例化 SomeClass 时我希望看到 "Hello"在控制台中,但不明白。为什么?

此外,我希望在实例化多个对象时只看到一次“Hello”,但在控制台中看不到任何“Hello”

最佳答案

我不知道这是否应该被视为一个错误,但这是如何发生的。

如果查看生成的字节码 object A , 就像这样:

public final class A$ {
public static final A$ MODULE$;

private final scala.runtime.BoxedUnit init;

public static {};
Code:
0: new #2 // class A$
3: invokespecial #12 // Method "<init>":()V
6: return

public void init();
Code:
0: return

private A$();
Code:
0: aload_0
1: invokespecial #16 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #18 // Field MODULE$:LA$;
8: aload_0
9: getstatic #23 // Field scala/Predef$.MODULE$:Lscala/Predef$;
12: ldc #25 // String Hello
14: invokevirtual #29 // Method scala/Predef$.println:(Ljava/lang/Object;)V
17: getstatic #34 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
20: putfield #36 // Field init:Lscala/runtime/BoxedUnit;
23: return
}

您可以找到 println("Hello")您期望在 A$ 的构造函数中,但在 init() 中什么也没有.这是完全正确的,因为您的意图是 println("Hello")不会每次调用 init() 时都执行, 对?

然而,问题出在 SomeClass :
public class SomeClass implements SomeTrait {
public void a();
Code:
0: return

public void SomeTrait$_setter_$a_$eq(scala.runtime.BoxedUnit);
Code:
0: return

public SomeClass();
Code:
0: aload_0
1: invokespecial #21 // Method java/lang/Object."<init>":()V
4: aload_0
5: invokestatic #27 // Method SomeTrait$class.$init$:(LSomeTrait;)V
8: return
}

什么?! SomeClass.a()中什么都没有, 任何一个!但想想看,这也是完全合理的:我为什么要费心调用它,因为 A$.init() 中几乎什么都没有。它什么都不返回(即没有要设置的字段)?为什么不直接优化它(也许 Java 做了这个优化。或者 Scala 做了。我不知道)?然而,这个优化也抹去了 A$的唯一出现。 ,这意味着不会为 A$ 调用构造函数.这就是为什么 Hello从未出现。

但是,如果你稍微改变一下代码,让 init() 的字节码不会是空的,像这样:
object A {
val init = { println("Hello"); 1 }
}

编译为以下字节码:
public int init();
Code:
0: aload_0
1: getfield #17 // Field init:I
4: ireturn

在这种情况下,您将找到 SomeClass.a() 的字节码像这样:
public int a();
Code:
0: aload_0
1: getfield #15 // Field a:I
4: ireturn

该字段在 SomeTrait$class 中设置的位置:
public abstract class SomeTrait$class {
public static void $init$(SomeTrait);
Code:
0: aload_0
1: getstatic #13 // Field A$.MODULE$:LA$;
4: invokevirtual #17 // Method A$.init:()I
7: invokeinterface #23, 2 // InterfaceMethod SomeTrait.SomeTrait$_setter_$a_$eq:(I)V
12: return
}
A$.init()被调用来设置这个字段,所以在这种情况下你可以期待 Hello出现。

关于Scala 对象初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24221601/

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