Почему работает автоматическое преобразование целочисленного типа в тип char Java?
Как всем известно, автоматическое преобразование целочисленного типа в тип char как собственно и в boolean в Java не поддерживается.
char ch = (char) 66; // правильно
char ch = 66; // по логике неправильно, но это работает
Почему автоматическое преобразование во втором случае работает? Если это не автоматическое преобразование, то что это?
Продолжая тему рассмотрим ещё один случай:
int i = 66;
char ch = i; // так не работает
char ch = (char) i; // так работает
Исходя из ответа добавлю ещё один пример. Если мы объявим не переменную а константу, то с ней будет так же работать, как и с литералом.
final int i = 66;
char ch = i; // теперь работает
Вот теперь мы готовы сделал определенные выводы. Автоматическое преобразование литерала числового типа (char ch = 66;) прекрасно работает. А автоматическое приведение числового типа (не литерала) не работает. Как известно из обширных источников интернета, литерал 66 по умолчанию имеет тип int - а это числовой тип. Так почему в таком случае происходит автоматическое преобразование в тип char?
Ответы (1 шт):
Все дело в том, что присваивание целочисленного литерала в переменную типа char является compile-time constant expression (константой этапа компиляции), которой может быть инициализирована переменная типа char:
char c = 66;
Здесь имеется одна оговорка. В связи с тем, что char представляет из себя 2-байтный тип данных(*), то не любой целочисленный литерал (имеющий тип int, размерность которого составляет 4 байта) может быть использован в качестве валидной для переменной типа char константы этапа компиляции:
char c1 = 1 << 15; // < 2^16 compilation ok
char c2 = 1 << 16; // >= 2^16 compilation error: incompatible types: possible lossy conversion from int to char
Другими словами, компилятор на этапе компиляции (трансляции java code -> byte code) валидирует размерность, т.е. проверяет конвертируемость значения целочисленного литерала в 2 байта без потерь.
В ситуации же когда в качестве значения переменной типа char используется значение переменной типа int, то ни о какой константе времени компиляции речи идти быть не может, т.к. значение переменной типа int, в общем случае, может изменяться в runtime (на этапе исполнения кода), как следствие, не может быть валидировано компилятором на соответствие размерности, т.е. кодируемости значения переменной типа int в 2 байта без потерь.
(*) внутренне данные в рамках типа char представлены в кодировке UTF-16.