我已经在笔记本电脑上尝试了以下源代码(Oracle HotSpot JVM,JDK 1.8、64位):
Long l;
Long l1 = 100L;
Long l2 = 100L;
System.out.println(Long.valueOf(100L) == Long.valueOf(100L));
System.out.println((l = 100L) == Long.valueOf(100L));
System.out.println(l1 == l2);
System.out.println(Long.valueOf(128L) == Long.valueOf(128L));
System.out.println(Long.valueOf(129L) == 129L);
System.out.println(Long.valueOf(255L) == new Long(255L));
Run Code Online (Sandbox Code Playgroud)
然后我在IntelliJ IDEA Community 2019.1中反编译了源代码以获得以下内容:
Long l1 = 100L;
Long l2 = 100L;
System.out.println(100L == 100L);
System.out.println(100L == 100L);
System.out.println(l1 == l2);
System.out.println(128L == 128L);
System.out.println(Long.valueOf(129L) == 129L);
System.out.println(255L == new Long(255L));
Run Code Online (Sandbox Code Playgroud)
我有答案:
true
true
true
false
true
false
Run Code Online (Sandbox Code Playgroud)
我已经知道,从原始数字到相应参考数字的整数赋值将自动装箱。如果数字在[-128,127]中,则将使用缓存,这意味着第4、5、6、7、9行的结果是合理的。
但是,我很好奇Java如何处理第8行中参考数字和原始数字之间的比较?换句话说,原始数实际上是如何存储在Oracle HotSpot JVM的内存中的?
到目前为止,我还没有找到任何帮助。任何建议将不胜感激。
更新2019年4月2日19点25分24秒:我试图表明的地址Long.valueOf(129L)和129L如下:
System.out.println(System.identityHashCode(Long.valueOf(129L)));
System.out.println(System.identityHashCode(129L));
System.out.println(System.identityHashCode(129L));
Run Code Online (Sandbox Code Playgroud)
我得到以下信息:
731260860
1709366259
1335298403
Run Code Online (Sandbox Code Playgroud)
它们显然是不同的对象,即使看起来它们是相同的原始数字129L。
关于 .class 文件反编译的任何奇怪的事情可能都无关紧要。它们可能只是意味着您使用的反编译器不可靠。因此,让我们忽略您的反编译代码。
测试原始数字类型和装箱数字类型相等性时的一般规则如下(简单版本):
<primitive-number> == <primitive-number>:
<primitive-number> == <boxed-number>或者<boxed-number> == <primitive-number>:
<boxed-number> == <boxed-number>
JLS 11 的相关部分是前两项的15.21.1和第三项的15.21.3 。(您应该发现,从 Java 5 开始,JLS 的所有版本基本上都说同样的事情。)
复杂的问题是,将相同的原始值装箱两次可能会也可能不会给您相同的引用。它取决于类型和值以及(在某些情况下)JVM 命令行开关(!)。
类型Byte、Short和Integer都Long为其值空间的子范围维护装箱值的缓存。通常,子范围是从 -128 到 +127(含),但这没有指定。如果您自动装箱该范围内的基元,您将获得缓存的值。如果您用于转换该范围1<Type>.valueOf(<prim-type>)内的值,则同样适用。但是如果你调用你将*总是得到一个新创建的对象。new <Type>(<prim-type>)
结论是,使用==比较两个盒装数字是一个坏主意,因为您得到的答案通常是不可预测的。
1 - 这是因为装箱被指定使用该valueOf方法。
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |