gpt4 book ai didi

java - Java如何处理原始数字和引用数字之间的长比较?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:27:39 25 4
gpt4 key购买 nike

我已经在笔记本电脑(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));

然后我在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));

我得到了答案:

true
true
true
false
true
false

我已经知道从原始数到对应的引用数的整数赋值会自动装箱。并且如果数字在[-128,127],就会使用缓存,这意味着第4、5、6、7、9行的结果是合理的。

不过,我很好奇Java是如何处理第8行的引用数和原始数的比较的?换句话说,原始数字实际上是如何存储在 Oracle HotSpot JVM 中的内存中的?

到目前为止我还没有找到任何帮助。任何建议将不胜感激。


更新于 2019-04-02 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));

我得到以下信息:

731260860
1709366259
1335298403

它们显然是不同的对象,即使看起来它们是相同的原始数,129L

最佳答案

关于 .class 文件反编译的任何奇怪的事情都可能无关紧要。它们可能只是表示您使用的反编译器不可靠。所以让我们忽略你的反编译代码。


测试基本类型和盒装数字类型是否相等的一般规则如下(简单版):

  • <primitive-number> == <primitive-number> :

    1. 如果值不是同一类型,则将“较小”的类型转换为较大的类型。
    2. 使用原始类型的排序进行比较
  • <primitive-number> == <boxed-number><boxed-number> == <primitive-number> :

    1. 将装箱的数字拆箱到它对应的原始类型
    2. 如果值不是同一类型,则将“较小”的类型转换为较大的类型。
    3. 使用原始类型的排序进行比较
  • <boxed-number> == <boxed-number>

    1. 如果盒装类型不同:编译错误
    2. 如果装箱的类型相同,则根据引用相等进行比较。

JLS 11 的相关部分是 15.21.1对于前两个项目符号和 15.21.3对于第三个。 (您会发现从 Java 5 开始的所有版本的 JLS 基本上都说同样的话。)

复杂的问题是两次装箱相同的原始值可能会也可能不会给你相同的引用。它取决于 JVM 命令行开关 (!) 的类型和值以及(在某些情况下)。

类型 Byte , Short , IntegerLong都为它们的值空间的子范围维护一个装箱值的缓存。通常,子范围是从 -128 到 +127(含),但这未指定。如果您自动装箱该范围内的原语,您将获得缓存的值。如果您使用 <Type>.valueOf(<prim-type>),这同样适用转换该范围内的值1。但是如果你调用new <Type>(<prim-type>)你将*总是得到一个新创建的对象。

要注意的是,使用 == 不是一个好主意。比较两个盒装数字,因为您得到的答案通常是不可预测的。


1 - 这是因为装箱指定使用 valueOf方法。

关于java - Java如何处理原始数字和引用数字之间的长比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55473101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com