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

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. Когда нет проблем с сужением, в чем проблема с расширением?

4b9b3361

Ответ 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.