Вопрос-ответ

Java - char, int conversions

Преобразования Java - char, int

В Java допускается следующее:

char c = 'A' + 1;

Здесь c будет содержать значение 'B'. Выше сначала вычисляется выражение. Итак, 'A' преобразуется в 65, все выражение вычисляется как 66, а затем 66 преобразуется в 'B', поскольку мы сохраняем значение в символе char.

Однако следующее выдает ошибку времени компиляции:

char c = 'A';
c = c + 1;

Чем объясняется то, что Java по-разному рассматривает выражения? Кстати, следующее тоже работает нормально:

char c = 'A';
c++;
Переведено автоматически
Ответ 1

Первый пример (который компилируется) является особенным, потому что оба операнда сложения являются литералами.

Несколько определений для начала:


  • Преобразование int в char называется сужающим примитивным преобразованием, потому что char это тип меньшего размера, чем int.



  • 'A' + 1 является постоянным выражением. Постоянное выражение - это (в основном) выражение, результат которого всегда один и тот же и может быть определен во время компиляции. В частности, 'A' + 1 является постоянным выражением, потому что операнды + оба являются литералами.



Преобразование с сужением допустимо при присваивании byte, short и char, если правая часть присваивания является постоянным выражением:


Кроме того, если выражение [в правой части] является постоянным выражением типа byte, short, char или int:



  • Может использоваться упрощенное преобразование с сужением, если переменная имеет тип byte, short или char, и значение константного выражения может быть представлено в типе переменной.


c + 1 это не постоянное выражение, потому что c это неfinal переменная, поэтому при присваивании возникает ошибка времени компиляции. Просматривая код, мы можем определить, что результат всегда один и тот же, но компилятору не разрешено делать это в данном случае.

Одна интересная вещь, которую мы можем сделать, заключается в следующем:

final char a = 'a';
char b = a + 1;

В этом случае a + 1 это постоянное выражение, потому что a это final переменная, которая инициализируется постоянным выражением.

Оговорка "если [...] значение [...] может быть представлено в типе переменной" означает, что следующее не будет скомпилировано:

char c = 'A' + 99999;

Значение 'A' + 99999 (которое равно 100064, или 0x186E0) слишком велико, чтобы вписаться в a char, потому что char это 16-разрядное целое число без знака.


Что касается постфиксного ++ оператора:


Тип выражения постфиксного приращения - это тип переменной.


...


Перед добавлением выполняется двоичное числовое увеличение* для значения 1 и значения переменной. При необходимости сумма сужается путем преобразования примитива с сужением и / или подвергается преобразованию в бокс до типа переменной перед ее сохранением.


(* Расширение двоичных чисел принимает byte, short и char операнды таких операторов, как + и преобразует их в int или какой-либо другой более крупный тип. Java не выполняет арифметику для целых типов, меньших, чем int.)

Другими словами, оператор c++; в основном эквивалентен:

c = (char)(c + 1);

(Разница в том, что результатом выражения c++, если мы присвоили его чему-либо, является значение c перед приращением.)

Другие приращения и декременты имеют очень похожие спецификации.

Составные операторы присваивания, такие как += также автоматически выполняют сужающее преобразование, поэтому такие выражения, как c += 1 (или даже c += 3.14) также разрешены.

Ответ 2

преобразование char в int называется расширяющими преобразованиями. При расширяющих преобразованиях значения не теряют информацию об общей величине числового значения, тогда как преобразование int в char называется уменьшающими преобразованиями. При уменьшении преобразования вы можете потерять информацию об общей величине числового значения, а также потерять точность.

Для получения дополнительной информации о примитивных преобразованиях обратитесь к этому документу.

Ответ 3

Это потому, что компилятор может проверить, что он ('A' + 1) находится в пределах символа, тогда как он не может (в общем случае) проверить, что c + <an integer> находится в пределах символа.

Ответ 4

Это потому, что литералы для целых чисел или меньших, чем int, таких как byte , short и char, являются int . Таким образом, поймите следующее.

код:

  byte a = 10;//compile fine
byte b= 11;//compile fine
byte c = a+b;//compiler error[says that result of **a+b** is **int**]

то же самое происходит для любых математических операций, таких как 'Divide', 'multiply' и других арифметических операций. итак, преобразуйте результат, чтобы получить литерал в желаемом типе данных

byte c = (byte)(a+b);

итак, когда вы выполняете

   c= c+1;//compiler error

Результатом c + 1 является int , а не char . поэтому компилятор выдает ошибку времени компиляции за то же самое.
итак, вам нужно предоставить примитивное приведение, чтобы изменить тип данных literal на char .
Надеюсь, этот пример даст некоторое представление..

java