Javaは、最初に静的変数をデフォルト値(null、0、および同等のもの)に初期化します。これは、初期値が指定されているかどうかに関係なく行われます。
次に、クラスの最初から最後まで、コードのすべての静的ブロック(静的メソッドではありません!)を実行します。初期化もコードのブロックと見なされ、ファイルで指定された順序で実行されます。したがって、そのようなコード:
// static block of code in front
static Type variable = initialValue;
// static block of code in-between
static OtherType anotherVariable = someInitialValue;
// static block of code below
ほぼ同等です(構文的に同等ではないため、ほぼ同等です)
static Type variable;
static OtherType anotherVariable;
// static block of code in front
static {
variable = initialValue;
}
// static block of code in-between
static {
anotherVariable = someInitialValue;
}
// static block of code below
(コンストラクターを呼び出す直前に、コンストラクターが呼び出される前にすべての非静的コードブロックが実行されます。ただし、OPのコードにはあまり関係ありません。)
上記のスキームから、Foo()
コンストラクターが呼び出されます。そしてcount1
、count2
1に初期化されます。
イニシャライザを実行した後、singleton = new Foo()
イニシャライザを実行しcount2 = 0
、実質的count2
に0に設定します。
この時点で、main()
関数に入り、印刷します。上記のように、コンストラクターが2回目に呼び出された場合、非静的なコードブロックがコンストラクターの前に実行され、コンストラクターが再度呼び出されて、値count1
とcount2
それぞれが1ずつインクリメントされます。このステップで奇妙なことは何も起こりません。
このコードをコンパイルして実行し、効果を確認できます。
class Foo {
static {
System.out.println("static 0: " + Foo.sigleton + " " + Foo.sigleton.count1 + " " + Foo.sigleton.count2);
}
private static Foo sigleton=new Foo();
static {
System.out.println("static 1: " + sigleton + " " + sigleton.count1 + " " + sigleton.count2);
}
private static int count1;
static {
System.out.println("static 2: " + sigleton + " " + sigleton.count1 + " " + sigleton.count2);
}
private static int count2=0;
static {
System.out.println("static 3: " + sigleton + " " + count1 + " " + count2);
}
{
System.out.println("non-static 1: " + sigleton + " " + count1 + " " + count2);
}
private Foo (){
count1++;
count2++;
System.out.println(count1 + " " + count2);
}
{
System.out.println("non-static 2: " + sigleton + " " + count1 + " " + count2);
}
public static Foo getInstance(){
return sigleton;
}
public static void main(String[] args) {
Foo f= Foo.getInstance(); // case 1
System.out.println(f.count1);
System.out.println(f.count2);
Foo t= new Foo(); // case 2
System.out.println(t.count1);
System.out.println(t.count2);
}
}