トップ 差分 一覧 Farm ソース 検索 ヘルプ PDF RSS ログイン

Java/シングルトン同士で呼びあう場合の挙動

[プログラミング]
[Java]

次のような二つのクラスを考える。これらのクラスでは、それぞれのコンストラクタで互いのインスタンスを取得しようとしている。

public class A{
  private static A instance = new A();
  public String mesg = "initial";
  public static A getInstance(){
    return instance;
  }
  private A(){
    System.out.println("A is instanciated.");
    B b = B.getInstance();
    mesg = "change";
  }
  public static void main(String args[]){
    A a = A.getInstance();
  }
}

public class B{
  private static B instance = new B();
  
  public static B getInstance(){
    return instance;
  }

  private B(){
    System.out.println("B is instanciated.");
    A a = A.getInstance();
    System.out.println(a.mesg);
  }
}

これをコンパイルして実行すると、

miyo@penne:% java A
A is instanciated.
B is instanciated.

となった後、処理が止まってしまう。
環境は、FreeBSD 5.3-RELEASE上のlinux_base-8-8.0_6によるlinuxエミュレータ上のJava 1.4.2_06である。

Javaでは
newの段階(瞬間?)で、コンストラクタのすべての処理が終了している保証はない
と人から聞いていたので、
逆にこのようなコードの場合、Bでは、a.mesgで"initial"が取得できてしまうのかなぁと思っていたのだけど...

さらに、MacやWindowsでも実験をしてみたところ、

C:?Documents and Settings?miyo>java -cp v:? A
A is instanciated.
B is instanciated.
Exception in thread "main" java.lang.ExceptionInInitializerError
        at A.<init>(A.java:13)
        at A.<clinit>(A.java:3)
Caused by: java.lang.NullPointerException
        at B.<init>(B.java:12)
        at B.<clinit>(B.java:3)
        ... 2 more

となって、例外を出力した。
コンストラクタがきちんと終了するまではインスタンスがきちんとnullになっているといいうことだろうか。