问题
我刚刚看到类似这样的代码:
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
}
}
运行时,这段代码将打印出来:
false
true
我理解为什么第一个是false
:因为这两个对象是单独的对象,所以==
比较引用。但我无法弄清楚,为什么第二个声明返回true
?当Integer的值在一定范围内时,是否会出现一些奇怪的自动装箱规则?这里发生了什么?
#1 热门回答(90 赞)
true
line实际上是由语言规范保证的。 Fromsection 5.1.7:
如果装箱的值为真,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两个装箱的结果p的转换始终是r1 == r2的情况。
讨论继续进行,建议虽然你的第二行产出是有保证的,但第一行却没有(参见下面引用的最后一段):
理想情况下,装箱给定的原始值p将始终产生相同的参考。实际上,使用现有的实现技术可能不可行。上述规则是务实的妥协。上面的最后一个条款要求将某些常见值装入无法区分的对象中。实现可以懒惰地或急切地缓存这些。对于其他值,此公式不允许对程序员的盒装值的身份进行任何假设。这将允许(但不要求)共享部分或全部这些引用。这确保了在大多数常见情况下,行为将是期望的行为,而不会造成过度的性能损失,尤其是在小型设备上。例如,较少内存限制的实现可以缓存所有字符和短路,以及-32K - 32K范围内的整数和长整数。
#2 热门回答(22 赞)
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000; //1
System.out.println(a == b);
Integer c = 100, d = 100; //2
System.out.println(c == d);
}
}
输出:
false
true
是的,第一个输出产生用于比较参考; 'a'和'b' - 这是两个不同的参考。在第1点,实际上创建了两个类似于 - 的引用
Integer a = new Integer(1000);
Integer b = new Integer(1000);
产生的第二个输出是因为JVM
以节省内存,当Integer
在一个范围内(从-128到127)。在第2点,没有为'd'创建类型为Integer的新引用。它不是为Integer类型引用变量'd'创建新对象,而是仅使用'c'引用的先前创建的对象进行分配。所有这些都是由JVM
完成的。
这些内存保存规则不仅适用于Integer。为了节省内存,以下包装器对象的两个实例(通过装箱创建)将始终为==,其原始值相同 -
- 布尔值
- 字节
- 从\ u0000到\ u007f的字符(7f为十进制127)
- 从-128到127的短整数
#3 热门回答(8 赞)
某些范围内的整数对象(我认为可能是-128到127)会被缓存并重新使用。该范围之外的整数每次都会获得一个新对象。