Java中的长文字

时间:2018-05-18 16:47:12

标签: java long-integer

因此,阅读文档,它指出如果你在结尾处声明一个带有L的int文字,它将把它读作long。这是我的问题:这是否有任何区别,只是将类型命名为一个很长的开头?例如:

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

同样的事情?

4 个答案:

答案 0 :(得分:3)

TL;博士

  

是否存在差异...... int x = 100L;long x = 100;

是。有一个主要的区别。

  • 第一个不会编译,也不会运行。
  • 第二个是32位int原始整数文字的加宽,同时被分配给64位long原始整数变量。

详细

其他答案中有很多错误信息。

32位与64位整数基元

上面显示的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

从32位扩展到64位

在下一行中,您首先要创建一个带有“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对象,并且赋值没有转换,所以你需要小心。

小心原始和对象类型,知道何时投射。