Java中的长字面量

问题描述 投票:2回答:4

因此,通读文档,它指出,如果声明一个以L结尾的int常量,它将改为读取long值。这是我的问题:这与将类型命名为很长的名称之间有什么区别吗?例如:

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

同一件事?

java long-integer
4个回答
6
投票

tl; dr

int x = 100L;long x = 100;有什么区别...>

是。有很大的不同。

  • 第一个不会编译,也不会运行。您不能将64位long填充为32位int
  • 第二个与第一个相反,一个32位int基本整数文字的widening
  • ,同时被分配给64位long基本整数变量。

    详细信息

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

32位与64位整数基元

上面看到的L表示“64-bitint整数primitive”,而在整数L中不存在literal的意思是“32-bitint整数基元”。

以下行无法编译。您试图将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.

原语,不是

对象

注意,与该页面上的其他答案相反,上面的代码具有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位整数的转换在技术上称为widening

。有关技术讨论,请参见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位适合,因此要切除的高32位的集合全为零。因此在这种情况下没有损坏。但在这种情况下,此代码也是毫无意义的,不应在实际工作中完成。确实,在实际工作中,只有很少(如果有的话)有生产性的理由,可以通过强制转换来剥夺一半的64位整数位。

缩小Math.toIntExact

比强制转换更好的选择是调用Math.toIntExact。您将Math.toIntExact原语传递给此方法,然后它返回long,即将64位整数缩小为32位整数的结果。与强制转换相比的优势在于,如果发生溢出,将抛出int。因此,您将收到有关任何数据丢失的通知。

ArithmeticException

对象

由于其他一些答案错误地提出了对象和自动装箱的主题,因此我将对此稍加提及。

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. } 的意思是Long class

而不是L原语。我不会在这里解释这种区别,只是说我希望Java从未明确使用基元,而是只坚持使用类。实际上,在不久的将来,Java版本很可能做到这一点(隐藏原语的存在)。

但是在此刻,类/对象和基元之间是有区别的。为了帮助消除这种区别,Java支持Long。为方便起见,在大多数情况下,Java编译器和运行时可以检测代码何时将基元分配给期望对象的位置,反之亦然。

long

上面的那一行实际上被视为:

auto-boxing

并且在逻辑上等同于以下内容,但是从技术上讲,此下一行失败(编译器错误),因为在字符串中不需要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. ,因为假定该字符串包含64位整数的数字。换句话说,此输入字符串是not

整数文字,因此Long myLongObject = Long.valueOf( 100L ) ; 是多余的,不允许使用。
L

仅从该String输入中删除L,因为假定该输入代表一个64位数字。

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

Java还将在自动装箱前从32位L自动扩展。因此,以上各行实际上也与此相同。

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

同样,在课题中看到的代码与类/对象有关。该答案的这一部分将是无关紧要的,只是其他不正确的答案引起了对象和自动装箱的问题。

int
是一个100的整数,在出现整数溢出的所有问题时,它将被扩展为一个长整数。

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,没有扩展。

因此使用大于long x = 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 变量关联。这称为

缩小原始转换

(您可以在long上了解更多信息)。A int将始终使用64位来表示其值,而int将使用32位。因此,将JLS Chapter 5值分配给long您将丢失32个数据,因为它们在存储空间中没有空间。变量。编译器会将其标记为错误,以保护您避免潜在的数据丢失。

但是您可以

cast

long转换为int(例如long),并且编译器会很好用,因为您现在应该知道那里可能发生数据丢失。
我不确定是否可以编译,因为您使用的是原始数据类型,但是如果您使用Number对象,请小心,因为100L是Long对象,并且您将其分配给Integer对象,并且分配没有强制转换,因此您需要注意这一点。

只需注意基本类型和对象类型,知道何时进行转换。


2
投票
int

1
投票
如注释中所述,您不能将Integer.MAX_VALUE文字与long x = 2147483648L; // will be the value that you expect it to be long y = 2147483648; // will not compile 变量关联。这称为

缩小原始转换


0
投票
我不确定是否可以编译,因为您使用的是原始数据类型,但是如果您使用Number对象,请小心,因为100L是Long对象,并且您将其分配给Integer对象,并且分配没有强制转换,因此您需要注意这一点。

只需注意基本类型和对象类型,知道何时进行转换。

© www.soinside.com 2019 - 2024. All rights reserved.