我正在阅读Scala编程,我不理解以下句子(pdf第112页):
每个单例对象都是作为从a引用的合成类的实例实现的 静态变量,因此它们具有与Java静态相同的初始化语义。
这是否意味着如果我在scala中有单个 FooBar ,编译器将创建一个名为 FooBar $ 的类?
作者的意思是“从静态变量引用”是什么意思?是否存在隐藏的静态变量,其中包含对某些 FooBar $ 类的引用?
我感谢你们的任何帮助。
答案 0 :(得分:24)
相同的“Scala编程”第31章更精确:
Java与单例对象没有完全等价,但它确实有静态方法。
单例对象的Scala转换使用静态和实例方法的组合。 对于每个Scala单例对象,编译器将为对象创建一个Java类,并在末尾添加美元符号。
对于名为App
的单个对象,编译器会生成一个名为App$
的Java类 该类包含Scala单例对象的所有方法和字段 Java类还有一个名为MODULE$
的静态字段来保存一个 在运行时创建的类的实例 作为一个完整的示例,假设您编译以下单例对象:
object App {
def main(args: Array[String]) {
println("Hello, world!")
}
}
Scala将使用以下字段和方法生成Java App $类:
$ javap App$
public final class App$ extends java.lang.Object
implements scala.ScalaObject{
public static final App$ MODULE$;
public static {};
public App$();
public void main(java.lang.String[]);
public int $tag();
}
这是一般情况的翻译。
答案 1 :(得分:10)
你基本上是对的。
如果你有单身人士
object Singleton {
def method = "Method result"
}
然后编译给你
Singleton.class
Singleton$.class
和您找到的字节码,首先是Singleton
:
public final class Singleton extends java.lang.Object{
public static final java.lang.String method();
Signature: ()Ljava/lang/String;
Code:
0: getstatic #11; //Field Singleton$.MODULE$:LSingleton$;
3: invokevirtual #13; //Method Singleton$.method:()Ljava/lang/String;
6: areturn
}
,即类的每个方法的公共静态方法,引用名为Singleton$.MODULE$
的内容,并在Singleton$
中:
public final class Singleton$ extends java.lang.Object implements scala.ScalaObject{
public static final Singleton$ MODULE$;
Signature: LSingleton$;
public static {};
Signature: ()V
Code:
0: new #9; //class Singleton$
3: invokespecial #12; //Method "<init>":()V
6: return
public java.lang.String method();
Signature: ()Ljava/lang/String;
Code:
0: ldc #16; //String Method result
2: areturn
private Singleton$();
Signature: ()V
Code:
0: aload_0
1: invokespecial #20; //Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #22; //Field MODULE$:LSingleton$;
8: return
}
您看到MODULE$
是Singleton$
的实例,而method
只是一种普通方法。
所以,这就是它的全部内容:使用名为Singleton$
的静态字段创建MODULE$
以保存其自身的唯一实例,填充该字段,然后创建Singleton
使用静态方法将所有静态调用转发到Singleton$
的适当方法。