Singleton 单例模式和Scala中的单例对象

  • 单例模式(JAVA vs Scala)

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
}

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

  • 使用Scala求校验和

import scala.collection.mutable.Map

class ChecksumAccumlator {

    private var sum=0

    def add(b:Byte):Unit=sum+=b

    def checksum(): Int = ~(sum & 0xFF)+1

}

object ChecksumAccumlator {

    private val cache = Map[String,Int]()

    def calculate(s:String):Int =

        if(cache.contains(s))

            cache(s)

        else{

            val acc = new ChecksumAccumlator

            for(c <- s)

                acc.add(c.toByte)

            val cs = acc.checksum()

            cache += (s -> cs)

            cs

        }

}

 

import ChecksumAccumlator.calculate

object Summer{
    def main(args : Array[String]) {
        for(arg <- args)
            println(arg + ": " + calculate(arg))
    }

Singleton 单例模式和Scala中的单例对象

  • 计算机内存的数据都是以补码的形式存放的

因为用吧补码表达一个数时,0的代码是唯一的。同时,补码进行运算时,数的符号不用单独处理,通过用补码进行表示,就可以把减法运算化为加法运算。

  • 补码取反加一与补码减一取反相同的证明

补码取反加一与补码减一取反相同的证明:

个位是1:
取反加一与减一取反都是从1变成为0,再变为1;
取反加一:取反从1变成为0,加一再变为1;
减一取反:减一从1变成为0,取反再变为1;

个位是0:说明该数的形式必为:1…(1或者0)…1(m个0); 其中(m的值为1~N),第(m+1)位的值为1,所以主要看前m+1位(即100…00)的原码与补码转换情况:
取反加一:取反前m+1位变为011…11,加一再变为100…00;
减一取反:减一前m+1位变为011…11,加一再变为100…00;

 

参考:梦想风暴 http://dreamhead.blogbus.com/logs/58331783.html

转载于:https://my.oschina.net/liango/blog/69663