私はインタビューでこの質問をされました。基本クラス(たとえばクラスA
)と2つのサブクラスB
とがありC
ます。現在、BとCのコンストラクターを制御することはできません(これらのコンストラクターはプライベートにすることはできず、パブリックにする必要があります)が、要件は、のすべてのインスタンスがシングルトンB
でC
ある必要があることです。どうすればこれを達成できますか?
2 に答える
のコンストラクターでこれを行うと思いますA
。を呼び出すように取得しthis.getClass()
、それを使用してプライベートHashSetでルックアップを実行します。ヒットした場合は、クラスのインスタンスが以前に作成されているため、例外がスローされます。
public abstract class A {
private static HashSet<Class<?>> classes = new HashSet<Class<?>>();
public A () {
synchronized (classes) {
Class<?> c = this.getClass();
if (classes.contains(c)) {
throw NotSingletonException("Class " + c + " is not singleton");
}
classes.add(c);
}
}
}
Aのすべてのコンストラクターがこれを行うように調整した場合、サブクラスはチェックを回避できません。this()
また、JLSでは、または呼び出しの周りにtry / catchを配置super()
できないため、その例外がスローされると、サブクラスのコンストラクターは正常に戻ることができなくなります。
これはかなり難しいインタビューの質問だと思います...
@emoryコメント:
BとCが最終的でない場合はどうなりますか?次に、クラスB1、B2、C1、C2などを作成できます。
ここでの問題(問題としてカウントされる場合)は、B1インスタンスとB2インスタンスもBインスタンスであるということです。つまり、実装しようとしているシングルトンの定義によっては、Bインスタンスがシングルトンではなくなったことを意味します。
私はこれに対処するいくつかの方法を見ることができます:
サブクラス修飾子を反射的にテストして、クラスが最終かどうかを確認し、万が一の場合に備えて、非最終クラスのインスタンスの作成を拒否することができます。
HashSet<Class>
をに置き換えることができList<Class>
ます。次に、コンストラクターが呼び出されるたびに、各要素クラスA
を呼び出すリストを繰り返し処理します。elem.isAssignableFrom(c)
いずれかの呼び出しがtrueを返す場合、(厳密な)シングルトン不変条件に違反しているため、例外をスローする必要があります。
強制しようとしているシングルトンネスのモデルに応じてロジックを調整する必要がある場合がありますが、一般的な解決策が適用されます。クラスを記録し、新しいクラスを以前のクラスと比較します。
クラスBに見せています
あなたはそれを使うことができますがDouble checked locking
、それsynchronized on method
をするために..私はあなたにそれをするための迅速で汚い方法を示しています...
public class B {
private static B b = new B();
private B() {}
public static B getInstance() {
return b;
}
}