Подтвердить что ты не робот

Невозможно определить приватную статическую конечную переменную, поскольку она выдает исключение

У меня есть класс вроде:

public class SomeClassImpl implements SomeClass {
   private static final SomeLib someLib = new SomeLib();
}

Я не могу этого сделать, потому что SomeLib выдает исключение UnknownHostException.

Я знаю, что могу перенести экземпляр в конструктор, но есть ли способ сделать это так, как я его каким-то образом выше? Таким образом, я могу сохранить var, отмеченный как final.

Я попытался найти, как бросать исключения на уровне класса, но ничего не могу найти на нем.

4b9b3361

Ответ 1

Вы можете использовать статический инициализатор:

public class SomeClassImpl implements SomeClass {
   private static final SomeLib someLib;
   static {
     SomeLib tmp = null;
     try {
       tmp = new SomeLib();
     } catch (UnknownHostException uhe) {
       // Handle exception.
     }
     someLib = tmp;
   }
}

Обратите внимание, что нам нужно использовать временную переменную, чтобы избежать ошибки инициализации переменной "someLib" и справиться с тем фактом, что мы можем присваивать только someLib один раз из-за того, что она final.

Однако необходимость добавления сложной логики инициализации и обработки исключений к статическому инициализатору часто является признаком более фундаментальной проблемы проектирования. В разделе комментариев вы написали, что это класс пула соединений с базой данных. Вместо использования статического final рассмотрим возможность создания переменной экземпляра. Затем вы можете выполнить инициализацию в конструкторе или еще лучше в статическом методе factory.

Ответ 2

Вы можете использовать статический инициализатор:

private static final SomeLib SOME_LIB; // respect naming conventions

static {
    try {
        SOME_LIB = new SomeLib();
    }
    catch (UnknownHostException e) {
        throw new RuntimeException("Class initialization failed due to UnknownHostException", e);
    }
}

Обратите внимание, что ваш класс не сможет инициализировать, если вы это сделаете. Возможно, вам следует попытаться инициализировать lib лениво, когда это необходимо. Такие исключения инициализации класса трудно диагностировать, потому что они преобразуются в ClassNotFoundException или NoClassDefFoundError (я не помню, какой)

Ответ 3

Даже немного более элегантно, чем решение от Адам Залчман:

public class SomeClassImpl implements SomeClass {
   private static final SomeLib someLib = initSomeLib();

   private static SomeLib initSomeLib() {
     SomeLib someLib = null;
     try {
       someLib = new SomeLib();
     } catch (UnknownHostException uhe) {
       // Handle exception.
     }
     return someLib;
   }

}

Ответ 4

Если инициализация переменной, скорее всего, завершится неудачей, то, вероятно, слабый кандидат будет статическим.

Статика хороша для [эффективных] неизменяемых, (с осторожностью) кешей неизменяемых и немного других.

Ответ 5

Этот пример кода даст вам представление об инициализации нескольких varibales без использования статического метода:

public class SomeClass implements SomeOtherClass{

private String string1= getValues("/var/log/log1.txt");
private String component = getValues("/var/log/log2.txt");

private String getValues(String file) {
        try {
          return  new Scanner(new File(file)).next();
        }catch(FileNotFoundException ioe){
            System.out.println("File not found :: " +ioe);
        }
        return null;
    }