Java-почему char получает неявное приведение к примитиву byte (и short), когда это не должно?
некоторые функции компилятора озадачивают меня (Oracle JDK 1.7 с использованием Eclipse).
Итак, у меня есть эта книга, в которой говорится, что примитив char должен быть явно приведен к short и byte, и все это имеет смысл из-за того, что допустимые диапазоны типов данных не перекрываются.
другими словами, ниже код работает (но не будет работать без явных приведений типов):
char c = '&';
byte b = (byte)c;
short s = (short)c;
печать b или s правильно отображает число 38, которое является числовым эквивалентом ( & ) в Юникод.
что подводит меня к моему фактическому вопросу. Почему работает и следующее?
byte bc = '&';
short sc = '&';
System.out.println(bc); // Correctly displays number 38 on the console
System.out.println(sc); // Correctly displays number 38 on the console
теперь я бы, конечно, понял следующее (что тоже работает):
byte bt = (byte)'&';
System.out.println(bt); // Correctly displays number 38 on the console
но этот символ предупреждения без компилятора для байтового (и короткого) "скрытого преобразования" не кажется мне правильным.
может кто-нибудь объяснить, почему это допускают?
может быть, причина в интерпретации '<char>'
сам, так что он на самом деле никогда не попадает в примитивное состояние char, но обрабатывается как числовое (восьмеричное или шестнадцатеричное и т. д.) значение?
5 ответов
в основном спецификация преобразования назначения указывает, что
кроме того, если выражение является константным выражением (§15.28) из введите byte, short, char или int:
можно использовать примитивное преобразование сужения, если тип переменная-byte, short или char, а значение константы выражение может быть представлено в типе переменной.
код '&'
Это точно "постоянное выражение типа byte, short, char или int".
Это называется сужение констант во время компиляции. Это описано в разделе 5.2 спецификации языка Java:
сужение времени компиляции констант означает, что код, такой как:
byte theAnswer = 42;
разрешено. Без сужения, тот факт, что целочисленный литерал 42 имеет тип int будет означает, что потребуется приведение к byte.
то же самое касается символьных литералов: если его значение соответствует byte
, преобразование не требуется; если значение не подходит, вы должны поместить в приведение, или вы получите ошибку компиляции.
например, это не будет компилироваться:
byte bc = '\uff12'; // Does not compile without a cast
но это прекрасно компилируется:
byte bc = (byte)'\uff12';
Я не знаю, достаточно ли этого объяснения или нет, но это поведение определено в JLS. От JLS, раздел 5.2:
кроме того, если выражение является константным выражением (§15.28) типа byte, short, char или int:
- сужающееся примитивное преобразование может используется, если тип переменной byte, short или char и значение постоянное выражение представимо в типе переменная.
- сужающееся примитивное преобразование с последующим боксом преобразование может использоваться, если тип переменная :
- Byte и значение постоянного выражения представимо в байте типа.
- короткое и значение константы выражение представимо в типа short.
- характер и значение постоянное выражение представимо в типе char.
почему работает следующее?
, потому что '&'
- постоянное выражение, значение которого соответствует byte
.
JLS 14.4.2
Если Декларатор имеет выражение инициализации, выражение вычисляется и его значение присваивается переменной.
JLS 5.2
преобразование присваивания происходит, когда значение выражения присваивается (§15.26) переменной: тип выражения должен быть преобразован в тип переменной.
....
кроме того, если выражение является постоянным выражением (§15.28) типа byte, short, char или int:
- сужающее примитивное преобразование может использоваться, если тип переменной-byte, short или char, а значение выражения константы можно представить в типе переменной.
выражение"&", которое находится в вашем инициализаторе для переменной bc, является постоянным выражением. Выражение c, которое находится в инициализаторе для переменных b и s, не является постоянным выражением. Java выполняет неявные сужающие преобразования примитивов, когда этого требует контекст когда значение является результатом постоянного выражения только.