Java "пустое конечное поле, возможно, не было инициализировано" Исключение, выброшенное в нечетности метода - PullRequest
14 голосов
/ 13 апреля 2011

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

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throwErrorMethod();
}

int var2 = var1;

И throwErrorMethod определяется примерно так:

private void throwErrorMethod() throws Exception{

   throw new Exception();

}

И я получаю blank final field may not have been initialized ошибку компиляции для оператора var2 = var1. Если я добавлю метод, компиляция будет в порядке!

  1. Разве компилятор не видит throws Exception в вызываемом методе?
  2. Почему ошибка, содержащая слово may, останавливает компиляцию?!?

Ответы [ 5 ]

19 голосов
/ 13 апреля 2011
  1. Нет, компилятор не определяет, что throwErrorMethod никогда не завершится нормально. Там нет ничего в спецификации, чтобы предположить, что это должно. К сожалению, нет способа указать, что метод никогда не вернется нормально.

  2. Это только "может", потому что есть потенциальный путь выполнения, который не инициализирует переменную. Наличие такого пути выполнения определено как ошибка.

Вы можете найти эту пару постов в блоге ( часть 1 ; часть 2 ) Эриком Липпертом интересной. Это скорее C #, а не Java, но тот же принцип.

7 голосов
/ 13 апреля 2011

Исключения должны быть исключительными. Он не предполагает, что исключение выдается всегда.

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

Если вы хотите бросить исключение всегда, вы можете сделать

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throw exceptionMethod();
}

int var2 = var1;

// later
public Exception exceptionMethod() {
    return new Exception("Complex-Exception-String");
}
1 голос
/ 13 апреля 2011

Если вы хотите сообщить компилятору, что ошибка обязательно будет выдана, но не хотите встроить логику для создания ошибки, вы можете сделать что-то вроде этого:

} else {
   throw createErrorMethod();
}

где createErrorMethod() декларируется как возвращающий какой-то тип Throwable.

1 голос
/ 13 апреля 2011

Компилятор не выполняет ту проверку, которую вы ожидаете. Он точно не определяет, что throwErrorMethod на самом деле выдает исключение каждый раз . Следовательно, предполагается, что можно перейти к предложению else, вызвать throwErrorMethod, возврат из этого метода , а затем не инициализировать var1 (который должен быть инициализирован).

0 голосов
/ 13 апреля 2011

Метод, объявленный как «throws Exception», не должен выбрасывать это исключение в любом пути выполнения.Поэтому компилятор не знает, будет ли метод всегда вызывать исключение, и также предполагает нормальное завершение.Таким образом, возможно, var1 не инициализирован.

...