Подтвердить что ты не робот

Примитивные роли и назначения в Java

Я понимаю, почему следующее неверно:

byte a = 3; 
byte b = 8; 
byte c = a + b;  // compile error

Он не будет компилироваться. Выражения всегда приводят к int. Итак, мы должны были сделать явный приведение:

byte c = (byte) (a + b);   // valid code

Но Я не понимаю, почему верно следующее:

byte d = 3 + 8;   // it valid! why?

Поскольку буквальное целое число (например, 3 или 8) всегда неявно является int. А выражения int-or-smaller всегда приводят к int тоже. Кто-нибудь может объяснить, что здесь происходит?

Единственное, что я могу догадаться, это то, что компилятор приравнивает это выражение к следующему:

byte d = 11;

и не считает это выражением.

4b9b3361

Ответ 1

Это меньше... зависит от того, оценивается ли 3 + 8 на 11 во время компиляции и больше связано с тем, что компилятору явно разрешено неявно сужать int до byte в в некоторых случаях. В частности, спецификация языка явно допускает неявное сужение преобразований в byte постоянных выражений типа int, которые могут быть в состоянии byte во время компиляции.

Соответствующий раздел JLS - это раздел §5.2:

Кроме того, если выражение является константным выражением (§15.28) типа byte, short, char, или int:

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

Сужение константы времени компиляции означает, что код, такой как: byte theAnswer = 42;позволено. Без сужения тот факт, что целочисленный литерал 42 имеет тип int, будет означает, что требуется приведение к byte:

†: Очевидно, что в соответствии с спецификацией выражение константы должно оцениваться, чтобы определить, подходит ли оно более узкому типу или нет. Но главное, что без этого раздела спецификации компилятору не будет разрешено делать неявное сужение преобразования.

Пусть здесь ясно:

byte a = 3; 
byte b = 8; 

Причина, по которой они разрешены, связана с вышеупомянутым разделом спецификации. То есть, компилятору разрешено сделать неявное сужение преобразования литерала 3 в byte. Это не потому, что компилятор оценивает константное выражение 3 его значение 3 во время компиляции.

Ответ 2

Единственное, что я могу догадаться, это то, что компилятор приравнивает это выражение к следующему:

Да, да. Пока выражение правой стороны состоит из констант (которые вписываются в необходимый примитивный тип - см. Ответ @Jason для того, что JLS говорит об этом точно), вы можете это сделать. Это не будет компилироваться, потому что 128 выходит за пределы допустимого диапазона:

byte a = 128;

Обратите внимание, что если вы преобразуете первый фрагмент кода следующим образом:

final byte a = 3; 
final byte b = 8; 
byte c = a + b;

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

Это, однако, не скомпилируется:

final byte a = 127; // Byte.MAX_VALUE
final byte b = 1;
byte c = a + b // Nope...

Компилятор выдает ошибку с "возможной потерей точности".

Ответ 3

Это потому, что 3 и 8 являются константами времени компиляции.

Поэтому во время компиляции компилятор может определить, что 3 + 8 может вписываться в переменную byte.

Если вы сделаете свои a и b конечной (постоянной) переменной. a + b станет константой времени компиляции. Поэтому он будет компилироваться без каких-либо проблем.

    final byte a = 3;
    final byte b = 8;
    byte c = a + b;