• 2010-02-09

    走进Scala——Singleton

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/58331783.html

    Singlton是一种为许多人熟知的设计模式,到了Scala这里,它成了语言的一部分,换句换说,我们不必像Java那样费劲的自己实现。下面就是一个Singleton:

    object Singleton {
      def show = println("I am a singleton")
    }
    (Singleton.scala)

    这里,我们用object进行声明,它会创建这个一个类,这个类只有一个实例,名字就叫Singleton。我们可以这样使用它:
      Singleton.show

    编译一下:
      scalac Singleton.scala

    不同于类的编译,Singleton编译出两个.class文件:Singleton.class和Singleton$.class。其实,真正称得上是Singleton的类是Singleton$,反编译一下,就可以看出来:
      javap -c Singleton$

    输出如下:
    public final class Singleton$ extends java.lang.Object implements scala.ScalaObject{
    public static final Singleton$ MODULE$;

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

    public void show();
      ...
    }

    其中,MODULE$是这个类唯一的实例,这个实例是在static块创建出来的。所以,Singleton.show这样的语句到了JVM的层面,就会变成这样:
      Singleton$.MODULE$.show();

    不知道你是否注意到,这个类里根本没有构造函数,换句话说,站在使用者的角度,我们根本就没有机会为这个类创建对象。如果你还不太适应这个没有构造函数的世界,可以参考《Javac背后的故事——空类》。

    我们都知道,javac会为没有构造函数的类生成一个缺省的构造函数,所以,在Java代码里,如果我们想实现Singleton必须显式声明出一个private的构造函数。而scalac绕过了javac直接生成字节码,它给出了一个用Java语言无法实现的Singleton方案。

    如果说Singleton$是真正的Singleton实现,那么还有个Singleton类是干什么的呢?先来反编译,看看它做了些什么:
      javap -c Singleton

    输出如下:
    public final class Singleton extends java.lang.Object{
    public static final void show();
      Code:
       0:    getstatic    #11; //Field Singleton$.MODULE$:LSingleton$;
       3:    invokevirtual    #13; //Method Singleton$.show:()V
       6:    return
    }

    我们看到了,这里有一个方法里同样有一个show方法,不同与Singleton$里的实现,它是static的,而它几乎是完全的透传,也就是说,这个方法实现是:
      public static final void show() {
        Singleton$.MODULE$.show();
      }

    这样一来,与Java互操作时,我们只要写Singleton.show()就可以了,不必理会Singleton$.MODULE$.show()这种对Java程序员来说很诡异的写法。不过,这还不是全部。

    分享到:

    历史上的今天:

    引用地址: