Ответ 1
Тип Java byte
- это 8-битный целочисленный тип со знаком со значениями в диапазоне от -128
до +127
. Литерал 0xff
представляет +255
, который находится вне этого диапазона.
В первом примере вы пытаетесь присвоить значение, которое находится вне диапазона, для byte
. Это ошибка компиляции.
Во втором примере приведение (byte)
выполняет явное сужающее преобразование, которое удаляет старшие биты целочисленного литерала... давая вам значение -127
в вашей переменной byte
.
На самом деле, ситуация с первым примером немного сложнее. Учтите это:
byte a = 1; // OK
int i = 1;
byte b = i; // Compilation error
byte c = (byte) i; // OK
В обычных обстоятельствах вы не можете назначить int
на byte
без приведения. Однако если присваиваемое значение является литералом, а литеральное значение находится в диапазоне целевого типа, язык Java разрешает присваивание без приведения. Литеральное значение неявно сужается от int
до byte
.
Это описано в JLS §5.2, в котором определяются преобразования, которые могут быть выполнены в назначении:
"Преобразование примитивного сужения может использоваться, если тип переменной - байтовый, короткий или символьный, а значение константного выражения представимо в типе переменной".
И, как вы можете видеть, это относится не только к литералам. Это относится ко всем (во время компиляции) константным выражениям!
ПОСЛЕДУЮЩИЕ UP
Я прочитал ответ, утверждая, что
0xff
это255
, как же так? Разве это не1111 1111
, что делает0xff
,-128
или255
или что-то в этом роде?
Литерал 0xff
является целочисленным литералом типа int
. Значение int
литерала 0xff
на самом деле является 0000 0000 0000 0000 0000 0000 1111 1111
в двоичном или +255 в десятичном виде. Напротив, целочисленное значение -128
имеет битовую комбинацию 1111 1111 1111 1111 1111 1111 1000 0000
.
Почему он не будет трактовать его как
1111 1111
, а не как 8 битов этого байта в 1?
Потому что 0xff
является целочисленным литералом с типом int
. Это не 8-битный литерал, потому что 8-битные литералы не существуют в Java. JLS §3.10.1 гласит:
"Целочисленный литерал имеет тип
long
, если к нему добавляется суффикс ASCII-буквыL
илиl
(ell); в противном случае он относится к типуint
(§4.2.1). "