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`.
Опять же, код, приведенный в Вопросе, имеет нет взаимодействия с классами / объектами.Этот раздел этого Ответа был бы неуместен, за исключением того, что другие неправильные Ответы поднимали вопросы об объектах и автобоксе.