2014-03-05 3 views
27

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

char c = 'c'; 
char d = c + 5; 

Ошибка на второй линии говорит

possible loss of precision 
    required: char 
    found: int 

Сообщение об ошибке на основе IDE NetBeans.


Когда этот символ c объявлен final как следующим образом.

final char c = 'c'; 
char d = c + 5; 

Ошибка компилятора-времени.

Это не имеет никакого отношения к случаю final strings

Что модификатор final сделать разницу здесь?

+2

Является ли компилятор достаточно умным, чтобы увидеть, что во втором случае константа 'c + 5' является постоянной? – vikingsteve

+1

Хороший вопрос, ответ должен быть где-то в JLS ... Подождем, пока кто-нибудь так хорошо его найдет. – skiwi

+0

Отметьте [этот ответ] (http://stackoverflow.com/a/21187200/1686291) –

ответ

24

Причина заключается в том, что JLS #5.2 (Assignment conversion) говорит так:

Если выражение является постоянным выражением (§15.28) типа байт, короткий, полукокса, или Int, сужение примитивно преобразование может быть использовано, если Тип переменной - это байт, короткий или char, а значение константного выражения представляется в типе переменной.

В вашем примере, char c = 'c'; не a constant но final char c = 'c'; есть.

Обоснование, вероятно, заключается в том, что оператор сложения + сначала преобразует свои операнды в целые числа. Таким образом, операция может переполняться, если все не является постоянным, и в этом случае компилятор может доказать, что переполнение не происходит.

+0

Был готов опубликовать его :) –

+1

Я думаю, что это принадлежит Джошу Блоху * Jave Puzzlers * :) – einnocent

+1

Я бы добавил, что даже если c не является окончательным, если вы используете оператор + = (он имеет неявное литье, но c = c + i;), поэтому c + = i совпадает с c = (char) (c + 1); На всякий случай вы хотите добавить его в ответ в качестве подсказки – Frakcool

15

When you apply the + operator to integral types

Binary числовое расширение выполняется над операндами (§5.6.2).

В этом случае char значения повышаются до int значений.

Здесь

char c = 'c'; 
char d = c + 5; 

потому c не константа, компилятор не может определить, является ли значение c + 5 которое является int сможет поместиться в char.

В этом

final char c = 'c'; 
char d = c + 5; 

где c является постоянным выражением, компилятор может определить, что значение c, которое 99, добавляет к 5, который делает 104 вписывается в char. Из-за этой гарантии Java может безопасно выполнять суживающее преобразование от int до char.

Если вместо этого вы были

final char a = Character.MAX_VALUE;  
char b = (a + 5); 

вы увидите подобное поведение, как при первом испытании случае в качестве значения a + 5 не вписывается в char. Компилятор определяет, что значение int, полученное в результате a + 5, не помещается в char.

+3

+1 лучшее объяснение в IMHO. – Songo

+0

+1, лучше, поскольку он явно указывает, что в представлении компиляторов 'c' может измениться между этими утверждениями. – TC1

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