为了账号安全,请及时绑定邮箱和手机立即绑定

为什么Integer常量池的行为在127发生变化?

为什么Integer常量池的行为在127发生变化?

Qyouu 2019-10-10 16:11:25
我无法理解Java常量池常量的工作方式。我了解字符串的行为,因此可以证明自己与整数常量也是如此。所以,对于整数Integer i1 = 127;Integer i2 = 127;System.out.println(i1==i2); // True和Integer i1 = new Integer(127);Integer i2 = new Integer(127);System.out.println(i1==i2); // False直到这里一切都进入我的脑海。我无法消化的是,当我从127增加整数时,它的行为有所不同。此行为在127之后发生变化,下面是代码段Integer i1 = 128;Integer i2 = 128;System.out.println(i1==i2); // False. WHY?????有人可以帮我理解吗?
查看完整描述

3 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

不,数字常量池的工作方式不同于字符串。对于字符串,只保留编译时常量-而对于整数类型的包装器类型,如果任何装箱操作都适用于该值,则任何装箱操作都将始终使用该池。因此,例如:


int x = 10;

int y = x + 1;

Integer z = y; // Not a compile-time constant!

Integer constant = 11;

System.out.println(z == constant); // true; reference comparison

JLS保证池值的范围很小,但是实现可以根据需要使用更大的范围。


请注意,尽管不能保证,但是我看过的每个实现都可以Integer.valueOf用来执行装箱操作-因此,即使没有该语言的帮助,您也可以得到相同的效果:


Integer x = Integer.valueOf(100);

Integer y = Integer.valueOf(100);

System.out.println(x == y); // true

从JLS的5.1.7节开始:


如果装箱的值p为true,false,一个字节或介于\ u0000到\ u007f范围内的char或-128到127(含)之间的整数或短数,则令r1和r2为p的任何两次拳击转换。r1 == r2总是这样。


理想情况下,将给定的原始值p装箱将始终产生相同的参考。实际上,使用现有的实现技术可能不可行。以上规则是一种务实的妥协。上面的最后一个子句要求始终将某些通用值装在无法区分的对象中。该实现可以懒惰地或急切地缓存它们。对于其他值,此公式不允许对程序员方面的带框值的身份进行任何假设。这将允许(但不要求)共享部分或全部这些引用。


这样可以确保在大多数情况下,行为都是理想的,而不会造成不必要的性能损失,尤其是在小型设备上。例如,较少内存限制的实现可能会缓存所有char和short值,以及-32K到+ 32K范围内的int和long值。


查看完整回答
反对 回复 2019-10-10
?
三国纷争

TA贡献1804条经验 获得超7个赞

Java维护从-128到的Integer池127


像下面这样声明整数


Integer i1 = 127;

结果到


Integer i1 = Integer.valueOf(127);

所以第一种情况实际发生的是


Integer i1 = 127;<---Integer.valueOf(127);

Integer i2 = 127;<---Integer.valueOf(127);<---Same reference as first

从Integerfor类  valueOf 方法的源代码


public static Integer valueOf(int i) {

    if(i >= -128 && i <= IntegerCache.high)

        return IntegerCache.cache[i + 128];

    else

        return new Integer(i);

}

因此,如果值介于-128到之间,则得到相同的引用,127然后调用valueOf它,否则它将返回new Integer(i)


并且由于引用相同,因此您的==运算符适用valueOf于此范围之间返回的整数。


查看完整回答
反对 回复 2019-10-10
?
HUX布斯

TA贡献1876条经验 获得超6个赞

Java缓存range中的整数对象-128 to 127。因此,当您尝试在此范围内为wrapper对象分配一个值时,该boxing操作将调用Integer.valueOf方法,然后它将对池中已存在的对象分配一个引用。


另一方面,如果将超出此范围的值分配给wrapper引用类型,Integer.valueOf则会Integer为该值创建一个新对象。因此,比较具有超出此范围值的referencefor Integer对象将为您提供false


所以,


Integer i = 127;  --> // Equivalent to `Integer.valueOf(127)`

Integer i2 = 127;


// Equivalent to `Integer.valueOf(128)`

// returns `new Integer(128)` for value outside the `Range - [-128, 127]`

Integer i3 = 128; 

Integer i4 = 128;


System.out.println(i == i2); // true, reference pointing to same literal

System.out.println(i3 == i4); // false, reference pointing to different objects

但是,当您使用new运算符创建整数实例时,将在堆上创建一个新对象。所以,


Integer i = new Integer(127);

Integer i2 = new Integer(127);


System.out.println(i == i2); // false


查看完整回答
反对 回复 2019-10-10
  • 3 回答
  • 0 关注
  • 793 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信