не могу инициализировать статическую конечную переменную в try/catch

Я пытаюсь инициализировать статическую конечную переменную. Однако эта переменная инициализируется в методе, который может генерировать исключение, поэтому мне нужно иметь внутри блок try catch.

Даже если я знаю, что эта переменная будет инициализирована либо в блоке try, либо в блоке catch, компилятор java выдает ошибку

Последнее поле a может быть уже назначено

Это мой код:

public class TestClass {

  private static final String a;

  static {
    try {
      a = fn(); // ERROR
    } catch (Exception e) {
      a = null;
    }
  }

  private static String fn() throws Exception {
    throw new Exception("Forced exception to illustrate");
  }

}

Я попробовал другой подход, объявив его как null напрямую, но он показывает аналогичную ошибку (в этом случае мне это кажется совершенно логичным)

Последнее поле TestClass.a не может быть назначено

public class TestClass {

  private static final String a = null;

  static {
    try {
      a = fn(); // ERROR
    } catch (Exception e) {
    }
  }

  private static String fn() throws Exception {
    throw new Exception("Forced exception to illustrate");
  }

}

Есть ли элегантное решение для этого?


person Mayday    schedule 23.04.2018    source источник
comment
Попробуйте передать временную переменную b в свой try...catch, проверьте результат и после него присвойте a значение   -  person Kaddath    schedule 23.04.2018


Ответы (4)


Вы можете сначала присвоить значение локальной переменной, а затем присвоить его переменной final после блока try-catch:

private static final String a;

static {

    String value = null;
    try {
        value = fn();
    } catch (Exception e) {
    }
    a = value;

}

Это обеспечивает единственное присвоение переменной final.

person Eran    schedule 23.04.2018

Конечные переменные можно задать только один раз.

Вы не можете (и не должны) устанавливать a в null в блоке catch.

Внесите следующие изменения:

public class TestClass {


      private static final String a = setupField();

      private static String setupField() {
        String s = "";
        try {
            s = fn();
        } catch (Exception e) {
          // Log the exception, etc.
        }
        return s;
      }

      private static String fn() throws Exception {
        return "Desired value here";
      }
person Austin Schäfer    schedule 23.04.2018
comment
Это приведет к другой ошибке — The blank final field a may not have been initialized — поскольку теперь a не гарантируется инициализация статическим блоком инициализатора. - person Eran; 23.04.2018
comment
Что ж, теперь у вас есть два присваивания переменной final (первая ошибка) и метод, который должен возвращать строку, но не имеет оператора возврата (вторая ошибка). - person Eran; 23.04.2018

частная статическая финальная строка a = null;

окончательные свойства инициализируются только один раз. Либо в Конструкторе, либо так, как вы это сделали здесь. Вы не можете присвоить 'a' новое значение после того, как вы присвоили ему значение null. Если у вас нет финала, вы можете установить значение с помощью функции fn

person Marcus Lanvers    schedule 23.04.2018

Это связано с тем, что переменная final может быть назначена только один раз и не может быть переназначена повторно.

Ничего общего с try/catch

person Shubhendu Pramanik    schedule 23.04.2018
comment
final переменная может быть назначена только один раз во время объявления. Это неправда, разве вы не слышали о пустых финалах? - person Kayaman; 23.04.2018
comment
есть связь с try...catch в том, как эффективно проверяется код в try, так что a был назначен уже при достижении catch, если есть ошибка, вопреки тому, что ожидал OP. - person Kaddath; 23.04.2018