У меня есть библиотека, которую я должен использовать, у которой есть опасная инициализация статического значения (для примера классы были сокращены до минимума):- это 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
Потому что я должен использовать этот класс, я ищу, чтобы наследовать от него, и попытаться принять меры, чтобы гарантировать, что инициализация имеет место при доступе к статическим.
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();
}
}
Который позволяет мне
MyBaseClass.Initialize();
Paths.get(MyBaseClass.PathToUse).toFile()....
Это, кажется, работает достаточно хорошо (и устраняет некоторые другие дефекты фантомные мы имели). Он позволяет TheirBaseClass
функционировать естественным образом, позволяя мне безопасно принудительно инициализировать в нескольких случаях, которые мне могут понадобиться.
Однако, когда я запускаю FindBugs против этого кода, я получаю JLM_JSR166_UTILCONCURRENT_MONITORENTER
. После прочтения описания, я согласен, что использование AtomicBoolean
может быть опасно, потому что кто-то может изменить значение, но ...
- Я думаю, что его можно проигнорировать в этом случае (но есть сомнения)
- Я вообще предпочитаю переписать код, чем поставить маркер игнорирования на место
Я действительно делаю что-то опасное (и просто не вижу его)? Есть лучший способ сделать это?
К сожалению, использование другого TheirBaseClass
не является вариантом.
Связанные
Я думаю, что я сделал большую ошибку в моем примере: я не расширил 'ИхBaseClass' –
Мне пришлось обдумать это. Я уже внедряю «ленивый держатель». Ваш ответ верный, но путаница, кажется, возникает вокруг логического: это совершенно необходимо. Я представил это для конкретного случая, но этот случай, похоже, ушел с большим количеством рефакторинга. –
Boolean не нужно * если я делаю инициализатор приватным * –