1

これはシングルトンクラスです。

このコードでシングルトンロジックを破る方法を知りたかった

class Employee{ // class starts
    private Employee(){} // private constructor

    private static Employee emp; 
    /*static block*/

    static {    
        if (emp==null)
        {
            emp=new Employee(); 
        }
    }      
    /* static method*/          
    public static Employee getEmployee()
    {   
        return emp;  
    }
}
4

4 に答える 4

7

Employee?のインスタンスを1つだけ必要です。

class Employee{ // class starts
   private Employee(){}
   public static final Employee INSTANCE = new Employee(); 
}

ゲッターは必要ありません。コードは現状のままで安全です。次を使用するだけです。

Employee.INSTANCE

注:Employee値オブジェクトのように聞こえますが、シングルトン値オブジェクトがあるのは珍しいようです。

更新:質問が何であるかをようやく理解したようです。このシングルトンは、非常に重いアーティレリーが使用されていない限り、安全です。

  • リフレクションを使用してコンストラクターを作成します( Marko Topolnikpublicによるすばらしい回答を参照してください)。これは、いくつかのセキュリティマネージャの設定で回避できると思います

  • Javaのシリアル化-実際には不可能です。シングルトンは実装する必要がありますSerializable

  • さまざまなクラスローダー(図解

これらの一般的な落とし穴に加えて、コードは問題ありませんが、きれいではありません。staticクラスがロードされると、初期化は1回だけアトミックに実行されることが保証されます。

于 2012-10-25T10:26:04.110 に答える
5

Employee複数のインスタンスにアクセスする場合は、コンストラクターをパブリックにするだけで十分です。このクラスの現在のすべてのクライアントが、シングルトンインスタンスではなく、毎回新しいインスタンスを受け取るようにする場合は、として実装getEmployee(){ return new Employee(); }ます。private staticその後、変数とstatic初期化ブロックを削除できます。

第三に、ソースコードを変更できないが、Employeeとにかく多くのインスタンスを取得したい場合、唯一の方法はリフレクションに頼ることです。

try {
  final Constructor<Employee> c = Employee.class.getDeclaredConstructor();
  c.setAccessible(true);
  final Employee e = c.newInstance();
} catch (Exception e) { throw new RuntimeException(e); }

第4に、質問が本当にシングルトンを違反から保護することであり、シングルトンが実際にシリアル化可能である場合(例には示されていません)、クラスreadResolveは逆シリアル化メカニズムに暗黙的に関与するメソッドを実装する必要があります。

protected Object readResolve() {
    return emp;
}

SecurityManagerを有効にして適切な特権を構成することを除いて、リフレクションから保護できるものは何もないことに注意してください。

于 2012-10-25T10:30:08.323 に答える
1

リフレクションによるオブジェクトの作成を回避するために、コンストラクターでも以下を実行する必要があります

private Employee(){ 
if(emp!=null){
   throws new InstantiationError("singleton breached ");
}

}

于 2012-10-25T13:33:28.113 に答える
0

複数のインスタンスが必要ですか?ケーキ:

    Constructor<Employee> constructor = Employee.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Employee wtf = constructor.newInstance();
    assertSame(wtf, Employee.getEmployee());

シングルトンを保護する方法は2つあります。次善の策は、1要素の列挙型を使用することです。

enum Singleton {
    INSTANCE;
    void doSomething(){
        System.out.println("Doing something");
    }
}

// Usage:
Singleton.INSTANCE.doSomething();

最良かつ最も簡単な方法は、シングルトンをまったく使用しないことです。

于 2012-10-25T13:50:28.273 に答える