1

この2つのクラスは同じですか?

public class SingleTone {

    // yes this is a bug what if i change the class this way
    //  private static SingleTone instance = new SingleTone();
    // and empty constructor?
    private static SingleTone instance; 
    private SingleTone() {
        instance = new SingleTone();
    }

    public static SingleTone getInstance(){
        return instance;
    }
} 

public class SingleTone {

    private final static SingleTone instance = new SingleTone();

    private SingleTone() {
    }

    public static SingleTone getInstance(){
        return instance;
    }
} 

コンストラクターによってインスタンス化された最終変数にスレッドセーフの問題はありますか?

質問2:

違いは何ですか

    private final static SingleTone instance = new SingleTone();

    private SingleTone() {
    }

この:

    private final static SingleTone instance;

    private SingleTone() {
        instance = new SingleTone();
    }
4

3 に答える 3

2

質問1

最初の例は機能しません。

SingleTone.getInstance()そのタイプのオブジェクトが作成される前にこの呼び出しを行った場合と同様に、null が返されます。

2番目の例は正常に動作します

質問2

同じ状況で、コンストラクターで静的フィールドを開始しています。static フィールドにアクセスする前にコンストラクターが呼び出されたことを保証できないため、これは意味がありません。

代わりにこれを行うことができます:

private final static SingleTone instance;

static {
    instance = new SingleTone();
}

これにより、クラスが最初にロードされたときに静的フィールドがインスタンス化されます。


コメントにお答えします。

これを行う場合:

private static final SingleTone instance = new SingleTone();

最初のスレッドがクラスの初期化を完了しておらず、別のスレッドがそれにアクセスしようとすると、他のスレッドがブロックするため、これはスレッドセーフです。

詳細については、この質問を参照してください: Java の静的ブロックのスレッド セーフ

于 2013-03-18T12:11:34.370 に答える
0

2つのオプションは実際には同じです(ただし、super()どちらの場合もコンストラクターの呼び出しがありません)。

ただし、プライベート静的フィールドを使用したJavaのシングルトンの実装は非推奨になる傾向があります。ここで、列挙型を使用します。

public enum Elvis {
    INSTANCE;
    private final String[] favoriteSongs =
        { "Hound Dog", "Heartbreak Hotel" };

    public void printFavorites() {
        System.out.println(Arrays.toString(favoriteSongs));
    }
}

さらに読みたい場合:http ://www.drdobbs.com/jvm/creating-and-destroying-java-objects-par/208403883?pgno = 3

于 2013-03-18T12:15:13.420 に答える
0

SingleTone クラスは参照を返す必要があるため、最初の例は完全に間違っています。

以下のプロセスを検討してください。 1. JVM によって開始されるクラスのロード 2. クラスが JVM にロードされます。3. コンストラクタの実行 4. オブジェクトの作成完了

public class SingleTone { この例では、インスタンスは 1 から 2 の間で有効になります。 private final static SingleTone インスタンス = new SingleTone();

private SingleTone() {
}

public static SingleTone getInstance(){
    return instance;
}

}

public class SingleTone { この例では、インスタンスは 3 ~ 4 個の非公開の最終的な静的な SingleTone インスタンスで動作します。

private SingleTone() {
    instance = new SingleTone();
}

public static SingleTone getInstance(){
    return instance;
}

}

于 2013-03-18T12:30:24.253 に答える