Преобразование с потерями из long в int, хотя с использованием литерала int в диапазоне int - PullRequest
1 голос
/ 05 ноября 2019

Я понимаю, что длинный литерал не может подходить для переменной типа int, пока я не приведу его:

long y = 1000000L;
int x = y;  // error - lossy conversion

Чего я не понимаю, так это зачем использовать литерал int вдиапазон int будет выдавать ту же ошибку:

long y = 100;
int x = y;  // error - lossy conversion

Литералом по умолчанию для целых чисел является 'int', так почему я не могу выполнить такую ​​операцию? Единственный ответ, который приходит ко мне, заключается в том, что, объявляя переменную как long, Java сохраняет значение как long, даже если я не добавляю суффикс «L», но мне нужно «официальное» объяснение.

Ответы [ 2 ]

6 голосов
/ 05 ноября 2019

Даже если вы сохраните в y значение, которое достаточно мало, чтобы поместиться в переменную int, позднее этой переменной можно будет присвоить новое значение, и это более позднее значение может не вписаться в int.

Поскольку такое назначение может иметь место во время выполнения, компилятор не может быть уверен, что назначение всегда будет иметь значение.

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

0 голосов
/ 05 ноября 2019

Вначале ваш вопрос выглядел просто, однако, немного разобрав его, я нашел концепцию, о которой раньше не слышал - неявное приведение типов

Как вы указали, объем памяти, взятый для int и longотличается: int - длинное 32-разрядное целое число со знаком - 64-разрядное целое число со знаком

И проблема в назначении длинного значения для int из-за разницы в размере. компилятор не будет выполнять числовые операции с вашим длинным значением, чтобы проверить, может ли оно вписаться в 32-разрядное целое число со знаком. например, число 1 по-разному представлено в памяти:

int 1 равно «00000000 00000000 00000000 00000001» (32-разрядный).

long 1 равно «00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001»"(64-разрядный).

, поэтому мы не можем выполнить неявное приведение типов к типам данных, которые не совместимы. Преобразование long int в int приведет к сбросу лишних старших битов.

Однакообратный путь применим! это называется неявным приведением типа или продвижением типа, и из-за этого вы можете присвоить int длинной переменной.

типы примитивов java в глубину https://www.ntu.edu.sg/home/ehchua/programming/java/J2_Basics.html

о продвижении типов http://www.java2s.com/Tutorials/Java/Data_Types/What_is_Java_type_promotion.htm

...