因此,阅读文档,它指出如果你在结尾处声明一个带有L的int文字,它将把它读作long。这是我的问题:这是否有任何区别,只是将类型命名为一个很长的开头?例如:
int x = 100L;
VS.
long x = 100;
同样的事情?
答案 0 :(得分:3)
是否存在差异......
int x = 100L;
与long x = 100;
是。有一个主要的区别。
int
原始整数文字的加宽,同时被分配给64位long
原始整数变量。其他答案中有很多错误信息。
上面显示的L
表示“64-bit int
整数primitive”,而整数literal中缺少L
表示“ 32-bit int
整数原语“。
以下行无法编译。您正在尝试将64位long
原始文字放入32位int
变量中。方形钉,圆孔。 compiler的工作之一是阻止这种无稽之谈。
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.
请注意,与此页面上显示的其他一些答案相反,上面的代码只有{em> no 对象,只有primitives。
在下一行中,您首先要创建一个带有“100”部分的32位int
基元。然后将该32位int
原语分配给64位long
原语。 Java用零填充额外的32位,因此有效地你得到相同的数字。
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.
正如Andreas的评论中所指出的,从32位到64位整数的转换在技术上称为扩展。有关技术讨论,请参阅JLS 5.1.2 Widening Primitive Conversion。
有些人,包括我在内,使用依赖于自动扩展的文字来考虑这样的代码。你作为程序员的意图是模棱两可的。所以我会使用附加的L
来编写代码,就像这个long x = 100L ;
一样。但有些人会认为这个立场不必要地担心一件无关紧要的事情。
与其他一些答案相反,上面的代码中包含 no casting。
这是一个铸造的例子。我们从64位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.
在这个特定的例子中,没有问题,因为一百的值适合低32位,所以被切除的高三十二位的集合都是零。所以在这种情况下没有损坏。但在这种情况下,这段代码也毫无意义,不应该在实际工作中完成。实际上,在实际工作中,你很少(如果有的话)有一个很有成效的理由通过强制转换掉一半的64位整数位。
因为其他一些Answers错误地提出了对象和自动装箱的主题,所以我会提到一点。
前面带有大写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
,因为假设输入代表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`.
同样,问题中看到的代码 no 涉及类/对象。本答案的这一部分是无关紧要的,除了其他不正确的答案提出了对象和问题的问题。自动装箱。
答案 1 :(得分:2)
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
答案 2 :(得分:1)
正如评论中所述,您无法为long
变量提供int
字面值。这被称为缩小基元转换(您可以在JLS Chapter 5阅读更多相关内容。)
long
将始终使用64位来表示它的值,而int将使用32.因此,为long
赋值int
,您将失去32位数据在变量中没有空间。编译器会将此标记为错误,以防止潜在的数据丢失。
然而,您可以 long
int
(例如int a=(int)1000L;
),编译器就可以了,因为你现在应该知道那里可能会发生数据丢失。
答案 3 :(得分:0)
我不确定是否因为你正在使用原始数据类型而编译但是如果使用Number对象要小心,因为100L是一个长对象,并且你将它分配给一个Integer对象,并且赋值没有转换,所以你需要小心。
小心原始和对象类型,知道何时投射。