Prev / Next / たまにっき。

シングルトンオブジェクトの lazy instantiation

Category: [Java]
2005-12-25

浅煎り珈琲オブジェクトの生成の抑制 にちょっと面白いのがあった.
private static final な singleton オブジェクトを lazy に初期化しようというものだ.
static final なので,クラスのロード時に初期化される必要があるが,本当に必要なときまで初期化を送らせたい.
それを実現するトリッキーな方法.

$ cat Singleton.java
class Singleton {
    static{
        System.out.println("Singleton loaded");
    }

    private Singleton(){
        System.out.println("Singleton instantiation");
    }

    private static class SingletonOnlyOne {
        static{
            System.out.println("Singleton.SingletonOnlyOne loaded");
        }
        private static final Singleton singleton = new Singleton();
    }
    public static Singleton getSingleton() {
        System.out.println("getSingleton");
        return SingletonOnlyOne.singleton;
    }

    public static void main(String[] args){
        System.out.println(getSingleton());
    }
}
$ javac Singleton.java
$ java Singleton
Singleton loaded
getSingleton
Singleton.SingletonOnlyOne loaded
Singleton instantiation
Singleton@131f71a


こんな感じ.インナークラス(static が付いているから正式にはインナークラスじゃないけど)からアウタークラスのコンストラクタを呼び出す.インナークラスはアウターのロード時にはロードされない.getSingleton メソッド内でインナークラスの private static final なフィールドを参照するときに始めてインナークラスがロードされ,singleton オブジェクトが初期化される.

こういう要求が本当にあるかは微妙.だって,getSingleton 呼び出しで初めてシングルトンなクラスがロードされることが多いだろう.
更に,別の解決法として,private static final なフィールドじゃなくて,private static なフィールドにして,getSinletonを以下のようにすれば良いから.

public synchronized static getSingleton(){
    if(instance == null){
        instance = new Singleton();
    }
    return instance;
}


本当にlazy instantiation したければ private static にして getSingleton 内で初期化するだろうな.

Category: [Java]