Длинные литералы в Java - PullRequest
0 голосов
/ 18 мая 2018

Итак, читая документацию, он заявляет, что если вы объявите литерал int с L в конце, он будет читать его как long.Вот мой вопрос: есть ли разница между этим и просто именованием типа как длинного для начала?Например:

int x = 100L;
VS.
long x = 100;

То же самое?

Ответы [ 4 ]

0 голосов
/ 19 мая 2018

tl; др

есть ли разница ... int x = 100L; против long x = 100;

Да.Есть большая разница.

  • Первый не скомпилируется и не запустится.
  • Вторым является расширение 32-битного int примитивного целочисленного литерала при назначении 64-битной long примитивной целочисленной переменной.

Детали

В других Ответах много дезинформации.

32-битные против 64-битных целочисленных примитивов

Вышеуказанное L означает « 64-бит int целое число примитив »тогда как отсутствие L в целом числе литерал означает « 32-битный int целочисленный примитив».

Следующая строка не компилируется.Вы пытаетесь поместить 64-битный long примитивный литерал в 32-битную int переменную.Квадратный колышек, круглое отверстие.Одна из задач компилятора состоит в том, чтобы остановить такую ​​ерунду.

int x = 100L ;  // BAD — compiler fails — Cannot place a 64-bit `long` `int` primitive in a 32-bit `int` variable.

Ошибка ... несовместимые типы: возможное преобразование с потерями из long в int

Давайте исправим эту строку, удалив L, назначив 32-битный литерал int 32-битной переменной int.

int x = 100 ;  // 32-bit `int` integer primitive literal being stored in a 32-bit `int` integer variable. No problem, no issues.

Примитивы, не объекты

Обратите внимание, что в отличие от некоторых других ответов, представленных на этой странице, приведенный выше код имеет нет объектов, только примитивы .

Расширение с 32-битного до 64-битного

В следующей строке вы сначала создаете 32-битный int примитив сЧасть «100».Этот 32-битный int примитив затем назначается 64-битному long примитиву.Java заполняет лишние тридцать два бита нулями, так что в итоге вы получите одно и то же число.

long x = 100 ;  // 32-bit `int` integer primitive being stored in a 64-bit `long` integer primitive. The extra 32-bits are filled in with zeros automatically by Java.

Как отмечено в комментарии Андреаса, это преобразование из 32-разрядных в 64-разрядные целые числа технически называется расширение .См. JLS 5.1.2 Расширение преобразования примитивов для технического обсуждения.

Некоторые люди, включая меня, считают такой код с использованием литералов, которые зависят от автоматического расширения, плохой формой.Ваши намерения как программиста неоднозначны.Поэтому я написал бы этот код, используя добавленный L, например, long x = 100L ;.Но некоторые люди считают эту позицию бесполезной из-за несущественного вопроса.

Кастинг

Вопреки некоторым другим ответам, есть нет кастинг участвует в коде, показанном выше.

Вот пример приведения.Мы начнем с 64-битного long примитива.Когда затем приведен к примитиву int, обрывает старшие 32-битные.(int) говорит компилятору: «Да, я знаю, что я рискую потерять данные, отсекая 32 из моих 64 битов, но продолжайте и сделайте это, я беру на себя ответственность за этот поступок».

int x = (int) 100L ;  // Start with a 64-bit `long` primitive literal, lop off 32 of the 64 bits, resulting in a 32-bit `int` primitive being assigned to a 32-bit primitive variable.

В этом конкретном примере нет проблем, так как значение в сотню соответствует младшим 32-битам, поэтому набор высших 32-битных вырезанных единиц - все нули.Так что никаких повреждений в этом случае.Но и в этом случае этот код не имеет смысла и не должен выполняться в реальной работе.На самом деле, в реальной работе у вас бы очень редко, если вообще когда-либо, была бы производительная причина отбросить половину битов 64-битного целого числа путем приведения.

Объекты

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

Формулировка Long сверхний регистр L спереди означает Long класс , а не long примитив.Я не буду объяснять это различие, за исключением того, что хочу сказать, что я бы хотел, чтобы Java никогда не использовала явные примитивы и вместо этого придерживалась только классов.Действительно, существует отдаленная вероятность того, что версия Java в далеком будущем может сделать именно это (скрыть существование примитивов).

Но здесь и сейчасСуществует различие между классами / объектами и примитивами.Чтобы помочь сгладить это различие, Java поддерживает auto-boxing .Для удобства в большинстве сценариев компилятор Java и среда выполнения могут определять, когда ваш код назначает примитив тому, где ожидается объект, и наоборот.

Long myLongObject = 100L ;  // This works because Java automatically detects the primitive `long` being assigned to an object of class `Long`, and instantiates a `Long` object to hold that number value.

Эта строка выше эффективно обрабатывается так, как если быэто:

Long myLongObject = Long.valueOf( 100L ) ;

И это было бы логически эквивалентно следующему, но технически эта следующая строка терпит неудачу (ошибка компилятора), потому что нет необходимости в L в строке, поскольку предполагается строкасодержать цифры 64-разрядного целого числа.Другими словами, эта входная строка является , а не целочисленным литералом, поэтому L является излишним и недопустимым.

Long myLongObject = Long.valueOf( "100L" ) ;  // Compiler error. The `L` is not allowed because it is redundant. 

Просто удалите L из этого ввода String,поскольку предполагается, что вход представляет 64-битное число.

Long myLongObject = Long.valueOf( "100" ) ;

Java также автоматически расширится с 32-битного int перед выполнением автобоксирования.Таким образом, приведенные выше строки также фактически совпадают с приведенными ниже.

Long myLongObject = Long.valueOf( 100 ) ;  // 32-bit `int` primitive literal automatically widened to a 64-bit `long`, then passed as argument to the `valueOf` method that takes only a `long`. 

Опять же, код, приведенный в Вопросе, имеет нет взаимодействия с классами / объектами.Этот раздел этого Ответа был бы неуместен, за исключением того, что другие неправильные Ответы поднимали вопросы об объектах и ​​автобоксе.

0 голосов
/ 18 мая 2018
long x = 100;

- это целое число 100, которое будет расширено до длинного со всеми проблемами переполнения целых чисел.

long x = 100L;

- это инициализированное длинное без расширения.

Так что вы будетеувидеть разницу при использовании числа, которое больше Integer.MAX_VALUE.

long x = 2147483648L; // will be the value that you expect it to be
long y = 2147483648;  // will not compile
0 голосов
/ 19 мая 2018

Как указано в комментариях, вы не можете присвоить литерал long переменной int.Это известно как сужающее примитивное преобразование (подробнее об этом можно прочитать в JLS, глава 5 ).

A long всегда будет использовать 64 бита для представленияэто значение, и int будет использовать 32. Таким образом, присваивая long значение int, вы потеряете 32 его данных, поскольку в переменной нет места для него.Компилятор пометит это как ошибку, чтобы защитить вас от возможной потери данных.

Однако вы можете привести a long к int (например, int a=(int)1000L;) ис этим будет работать компилятор, поскольку теперь вы должны знать , что там может произойти потеря данных.

0 голосов
/ 18 мая 2018

Я не уверен, что это компилируется, потому что вы используете примитивные типы данных, но если вы используете объект Number, будьте осторожны, потому что 100L - это длинный объект, и вы присваиваете его объекту Integer, а назначение выполняется без приведения, поэтому вы должны быть осторожны с этим.

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

...