私は静的な値の危険な初期化を持っているライブラリを持っています(この例ではクラスは最小限にされています):はFindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER'はこの場合無視してください
public TheirBaseClass {
public static String PathToUse = null;
public BaseClass(){
PathToUse = "Configured";
// ...
// do some other stuff with other side effects
// ...
}
}
値をConfigValue
から読み込み、クラスのインスタンスを作成せずに(一部の副作用を避けるため)、私はそのケースがあります。
Paths.get(TheirBaseClass.PathToUse).toFile()....
これは、静的にアクセスするとき、私はこのクラスを使用するために必要ですので、私はそれを継承し、その初期化を確実にするために行動を取るしようとしているよNullPointerException
が行われた原因となります。
MyBaseClass.Initialize();
Paths.get(MyBaseClass.PathToUse).toFile()....
に私を可能に
public MyBaseClass extends TheirBaseClass{
private static final AtomicBoolean isInitialized = new AtomicBoolean(false);
static {
MyBaseClass.Initialize();
}
public static void Initialize(){
// FindBugs does not like me synchronizing on a concurrent object
synchronized(isInitialized){
if(isInitialized.get()){
return;
}
new TheirBaseClass();
isInitialized.set(true);
}
}
public MyBaseClass(){
super();
}
}
は、この合理的にうまく機能しているようだ(と私たちが持ってきたいくつかの他のファントムの欠陥を解決します)。それはTheirBaseClass
が自然に機能することを可能にしますが、私が必要とするかもしれない2つのケースでは初期化を安全に強制することができます。
しかし、このコードに対してFindBugsを実行すると、JLM_JSR166_UTILCONCURRENT_MONITORENTER
となります。説明を読んだ後、私は
- が、私はこのケースでは無視してその安全を考える(ただし、疑問を持っている)...他の誰かが値を変更する可能性があるため
AtomicBoolean
の使用は危険なことができることを同意するが、 - 私は通常、無視マーカーを置くよりもコードを書き直すほうがいいです
私は実際に何か危険なことをしています(それは見えません)?これを行うより良い方法はありますか?
残念ながら、別のTheirBaseClass
を使用することはできません。
あなたはそれが簡単に適応するかもしれません
私は私の例で大失敗したと思う:私は 'TheirBaseClass'を拡張しなかった –
私はこれを熟考しなければならなかった。私はすでに 'lazy holder'を実装しています。あなたの答えは正しいですが、混乱はブール値の周りに発生しているように見えます。それはまったく必要ありません。私はそれを特定のケースで導入しましたが、そのケースはますますリファクタリングがなくなったようです。 –
ブール値は必要ありません*私は初期化子をプライベートにする場合* –