因此,通读文档会指出,如果声明一个以L结尾的int常量,它将改为读取long值。这是我的问题:这与将类型命名为很长的名称之间有什么区别吗?例如:
int x = 100L;
VS.
long x = 100;
Run Code Online (Sandbox Code Playgroud)
同样的事情?
有什么不同...
int x = 100L;对long x = 100;
是。有很大的不同。
long为32位int。int原始整数文字,同时将其分配给64位long原始整数变量。其他答案中有很多错误信息。
在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.
Run Code Online (Sandbox Code Playgroud)
错误…不兼容的类型:可能从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.
Run Code Online (Sandbox Code Playgroud)
请注意,与在此页面上看到的其他答案相反,以上代码没有对象,只有基元。
在下一行中,您首先要创建一个int带有“ 100”部分的32位原语。int然后将该32位原语分配给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.
Run Code Online (Sandbox Code Playgroud)
正如Andreas在评论中指出的那样,从32位整数到64位整数的这种转换在技术上被称为Widening。有关技术讨论,请参见JLS 5.1.2扩展基本转换。
包括我在内的某些人认为使用依赖于自动扩展的文字形式的此类代码是不好的形式。您作为程序员的意图是模棱两可的。因此,我将使用附加代码编写该代码L,如下所示long x = 100L ;。但是有些人会认为这个职位不必要地担心无关紧要的事情。
与其他答案相反,上面的代码中没有 强制转换。
这是强制转换的示例。我们从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.
Run Code Online (Sandbox Code Playgroud)
在此特定示例中,这没有问题,因为较低的32位的值是100,所以要切除的高32位的集合全为零。因此在这种情况下没有损坏。但在这种情况下,此代码也是毫无意义的,不应在实际工作中完成。的确,在实际工作中,只有很少(如果有的话)有生产性的理由可以通过强制转换来剥离64位整数的一半。
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.
}
Run Code Online (Sandbox Code Playgroud)
由于其他一些答案错误地提出了对象和自动装箱的主题,因此我将对此进行一些介绍。
前面Long带有大写字母的措辞是L指Long 类而不是long原始语种。我不会在这里解释这种区别,只是说我希望Java从未明确使用基元,而是只坚持使用类。实际上,在不久的将来,Java版本很可能做到这一点(隐藏原语的存在)。
但是在这里和现在,类/对象和基元之间是有区别的。为了帮助消除这种区别,Java支持自动装箱。为方便起见,在大多数情况下,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.
Run Code Online (Sandbox Code Playgroud)
上面的那一行实际上被视为:
Long myLongObject = Long.valueOf( 100L ) ;
Run Code Online (Sandbox Code Playgroud)
和在逻辑上等效于以下内容,但是从技术上讲,下一行失败(编译器错误),因为L在字符串中不需要使用,因为假定字符串包含64位整数。换句话说,此输入字符串不是整数文字,因此L多余且不允许使用。
Long myLongObject = Long.valueOf( "100L" ) ; // Compiler error. The `L` is not allowed because it is redundant.
Run Code Online (Sandbox Code Playgroud)
只需L从该String输入中删除,因为假定该输入代表一个64位数字。
Long myLongObject = Long.valueOf( "100" ) ;
Run Code Online (Sandbox Code Playgroud)
Java也将int在执行自动装箱操作之前从32位自动扩展。因此,以上各行实际上也与此相同。
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`.
Run Code Online (Sandbox Code Playgroud)
同样,在课题中看到的代码与类/对象无关。除了其他不正确的答案引发了对象和自动装箱问题之外,本答案的这一部分将是无关紧要的。
| 归档时间: |
|
| 查看次数: |
1566 次 |
| 最近记录: |