Java Примитивные преобразования в контексте назначения Long и int
Long ll = 102; // Error
Byte bb = 101; // No error
Почему Long
присваивание приводит к ошибке времени компиляции, в то время как Byte
назначение выполняется нормально?
Long ll = 102
приводит к ошибке компилятора "Тип несоответствия: невозможно преобразовать из int в Long". Я предположил, что компилятор расширит с 102 до Long
, а затем поле до Long
.
Но этого не происходит.
Но Byte bb = 101;
не генерирует ошибку компилятора. Здесь, как я полагаю, 101 сужается до Byte
(будучи недолгой интегральной константой), а затем вставляется в коробку до Byte
.
Когда нет проблем с сужением, в чем проблема с расширением?
Ответы
Ответ 1
См. 5.1.7 Бокс-конвертация JLS
- Если p является значением типа int, тогда преобразование бокса преобразует p в ссылку r класса и тип Integer, так что r.intValue() == p
Поскольку 102
является целым литералом, он имеет тип int
, и автоматический бокс преобразует его в Integer
(как говорит спецификация), но Integer
не может быть отправлен на Long
.
Таким образом, если вы используете литерал Long
или нарисуете литерал int
на Long
, JLS будет использовать преобразование бокса, а результатом будет объект Long
.
Это будет хорошо
Long long1 = (long) 102;
Long long2 = 102L;
Long long3 = 102l;
Второй
Byte bb = 101;
работает из-за 5.2. Преобразование присваивания
Кроме того, если выражение является константным выражением (§15.28) типа byte, short, char или int:
- Сужение примитивного преобразования может быть использовано, если тип переменной является байтом, коротким или char, а значение константного выражения представляется в типе переменной.
So 101
- целочисленный литерал, но есть назначение, которое требует сужающего преобразования (int → byte), а значение int
находится в пределах диапазона значений byte
. Таким образом, он представляется как тип переменной (см. Спецификацию) и преобразуется.
Это будет НЕ РАБОТАЕТ, конечно
Byte bb = 128; // can not be represented as the variable type. Thus no narrowing conversion.
Ответ 2
Это происходит потому, что вы используете Long
, а не Long
. Автобоксинг Java не будет конвертировать из int
в Long
, а затем autobox Long
в Long
на том же шаге.
Измените код на long ll
, и он будет работать.
В java для примитивов byte
нет маркера. Любое значение, введенное в допустимом диапазоне для byte
(от -128 до +127), можно рассматривать как a byte
или integer
в зависимости от контекст. В этом случае он обрабатывает его как byte
, а затем автооблок может работать над ним.
Я не уверен, почему было принято решение о том, что Java работает именно так. Кажется, что обработка байтов несовместима со всеми другими типами номеров.
Ответ 3
- Авто-бокс также не бросается; например, он будет автоматически помещать a
long
в long
, a int
в Integer
и т.д.
- В Java числовые литералы по своей сути
int
Итак, должно быть понятно, почему назначение long
не будет работать: a int
пытается быть добавлено к long
, затем автоматически помещается в long
за один шаг... no перейти.
Однако числовые литералы в диапазоне от -128
до 127
могут быть интерпретированы как byte
литералы в правильном контексте, так что работает назначение byte
.