阅读文档后,发现如果在int字面量后面加上L,它会将其视为long类型。我的问题是:这种方式和一开始就声明long类型有什么区别吗?例如:
int x = 100L;
VS.
long x = 100;
相同的事情?
阅读文档后,发现如果在int字面量后面加上L,它会将其视为long类型。我的问题是:这种方式和一开始就声明long类型有什么区别吗?例如:
int x = 100L;
VS.
long x = 100;
int x = 100L;
和long x = 100;
有区别。
有一个重大的区别。
long
塞入32位的int
中。int
原始整数字面值的扩展,同时被赋值给一个64位的long
原始整数变量。其他答案中存在许多错误信息。
L
表示“64位 int
整数 原始类型”,而在整数 字面量 中没有 L
则表示“32位 int
整数原始类型”。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.
请注意,与此页面上的其他答案相反,上面的代码没有对象,只有基本类型。
在下一行中,您首先使用“100”部分创建一个32位的int
基本类型。然后将该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.
L
编写该代码,就像这样long x = 100L ;
。但是有些人会认为这种立场对一个无关紧要的问题过分担心。
long
原始数据开始。然后将其转换为一个int
原始数据,去掉高32位。(int)
告诉编译器,“是的,我知道在截断我的64位中的32位时可能会丢失数据,但请继续执行,我对此负责。”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.
Math.toIntExact
收缩Math.toIntExact
。您将一个long
原语传递给此方法,它返回一个int
,即将64位整数收缩为32位整数的结果。与强制转换相比的优点是,如果发生溢出,则会抛出ArithmeticException
。因此,您将获得任何数据丢失的信息。try {
int x = java.lang.Math.toIntExact( 100L ) ;
} catch ( ArithmeticException e ) {
… // Handle data loss, the overflow in going from 64-bits to 32-bits.
}
由于其他答案错误地提到了对象和自动装箱的主题,我会稍微提一下。
以大写字母L
开头的单词Long
表示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
,因为假定该输入表示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`.
再次强调,问题中的代码与类/对象没有任何关系。这个答案的这一部分可能与此无关,只是因为其他不正确的答案涉及了对象和自动装箱。
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
100
不会被强制转换为 long
,而是会进行扩展。你可以使用强制转换来进行扩展转换,或者它也可以由编译器隐式完成(在这里)。但是,casting(JLS 15.16 Cast Expressions)和 widening(JLS 5.1.2 Widening Primitive Conversion)是两个不同的概念,需要区分开来,不能混淆。 - Andreasint
扩展为 long
据我所知并没有“整数溢出问题”,请解释。 - Basil Bourque正如评论中所述,您不能将一个long
字面值赋给一个int
变量。这被称为缩小原始转换(您可以在JLS第5章中了解更多信息)。
long
将始终使用64位来表示其值,而int
将使用32位。因此,将long
值分配给int
,您将失去32位数据,因为变量中没有空间。编译器将标记此为错误,以保护您免受潜在的数据丢失。
但是,您可以将long
强制转换为int
(例如:int a =(int)1000L;
),编译器会接受它,因为您现在应该知道可能会发生数据丢失。
int x = 100L
无法编译 - 您需要将其声明为长整型类型。我认为您可能想询问long x = 100;
与long x = 100L;
的区别。 - takendarkklong a=100L
和long a=100
的结果将是相同的。 - PM 77-1long l = 123123123123123123123123123123123;
,因为123123123123123123123123123123123
无法放入int
中。但是如果在末尾添加L
,就可以通过编译。 - Ivan