2015-06-11 2 views
42

В приведенном ниже коде:Почему конечная переменная всегда является постоянным выражением?

final int a; 
a=2; 
byte b=a; // error: possible loss of precision 

Почему я получаю эту ошибку? Не является ли a окончательным значением переменной времени компиляции переменной и, следовательно, неявно сужается до байта во время назначения?

Другими словами, не приведенный выше код эквивалентен:

final int a=2; 
byte b=a; 

ответ

40

Компилятор не такой умный.

We может сказать, что значение всегда будет 2. Но что, если бы у нас было что-то подобное?

class ABC{ 
    final int a; 

    public ABC(){ 
     if(Math.random() < .5){ 
      a = 2; 
     } 
     else{ 
      a = 12345; 
     } 

     byte b = a; 
    } 
} 

Компилятор недостаточно умен, чтобы рассказать обо всех этих случаях, поэтому вместо этого вы получите ошибку.

+30

На самом деле компилятор не может быть таким умным. – usr

+0

@usr Это какая-то серьезная примитивная религия. Серьезно: Почему? Компиляторы чувствительны к номерам '1',' 2', '4' и т. Д. При умножении. Случай в этом ответе явно неразрешим, потому что значения, возвращаемые из 'random', зависят от времени запуска программы. – LyingOnTheSky

+9

@LyingOnTheSky Но даже если вычисление было детерминированным, и компилятор мог понять это, ему все равно не разрешалось рассматривать его как постоянное выражение (устраняя необходимость в литье). Важно, что то, что является или не является допустимой программой java, не зависит от того, насколько интеллектуальным является конкретный компилятор. – CodesInChaos

49

От JLS

пустым final является final переменная, декларация не имеет инициализатора.

Постоянная переменная является переменной final примитивного типа или типа String, которая инициализируется постоянным выражением (§15.28).

Ваша переменная

final int a; 

является пустым final переменной. Ему не хватает инициализатора. Второй абзац не применяется к нему, поскольку он не инициализируется при объявлении. Поэтому он не является постоянным выражением.

Это относится и к полям.

2

Поскольку конечные переменные могут быть отложены инициализированы и компилятор не может определить для b, что он имеет значение в ветви case.

Смежные вопросы