【问题标题】:Singletons as Synthetic classes in Scala?单例作为 Scala 中的综合类?
【发布时间】:2011-04-19 18:38:21
【问题描述】:

我正在阅读 Programming in Scala,但我不明白以下句子(pdf p.112):

每个单例对象都作为一个合成类的实例来实现 静态变量,因此它们具有与 Java 静态相同的初始化语义。

这是否意味着如果我在 scala 中有一个单例 FooBar,编译器将创建一个名为 FooBar$ 的类?

另外作者所说的“从静态变量引用”是什么意思?某处是否有一个隐藏的静态变量持有对某些 FooBar$ 类的引用?

感谢您的帮助。

【问题讨论】:

  • 是的,我想你明白了。
  • :-( 我没有,我只是猜到了!
  • 诀窍在于静态变量引用的是实例,而不是类。换句话说,Scala 对象FooBar 在Java 中被引用为FooBar$.MODULE$

标签: scala


【解决方案1】:

同样的“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();
}

这是一般情况的翻译。

【讨论】:

【解决方案2】:

你基本上是正确的。

如果你有单身人士

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只是一个普通的方法。

所以,这就是它的全部内容:使用名为 MODULE$ 的静态字段创建 Singleton$ 以保存其自身的唯一实例,填充该字段,然后使用转发所有内容的静态方法创建 SingletonSingleton$ 对适当方法的静态调用。

【讨论】:

  • 谢谢,这很清楚,但是数字 0 1 4 等等是什么?抱歉,我对字节码不太熟悉,哈哈 :(
  • 在左边,它们是字节码地址。行号,本质上。在右侧,它们指的是类、方法、字段或其他任何适当的表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
相关资源
最近更新 更多