当前位置: 首页 > 知识库问答 >
问题:

为什么整数常数池的行为在127处发生变化?

慕容康安
2023-03-14

我无法理解整数的Java常量池是如何工作的。

我理解字符串的行为,因此能够证明整数常量也是同样的情况。

因此,对于整数

Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1==i2); // True

(&A)

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?????

有人能帮我理解一下吗?

共有2个答案

庄欣然
2023-03-14

Java维护从-128127的整数池

声明整数,如下所示

Integer i1 = 127;

结果为

Integer i1 = Integer.valueOf(127);

第一种情况下实际发生的是

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

来自类valueof方法integer的源代码

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

因此,如果value介于-128127之间,则获得相同的引用,并且调用valueof否则它只返回new Integer(i)

而且,由于引用相同,您的==运算符适用于valueof在此范围内返回的整数。

宰父冠玉
2023-03-14

不,数字的常量池与字符串的常量池的工作方式不同。对于字符串,只有编译时常量被内嵌-而对于整数类型的包装类型,任何装箱操作都将始终使用池,如果它适用于该值。例如:

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、byte或\u0000到\u007f范围内的char、或-128到127(含)之间的int或short数,则设r1和r2是p的任意两次装箱转换的结果。r1==R2总是这样。

理想情况下,装箱一个给定的基元值p总是会产生一个相同的引用。在实践中,使用现有的实现技术,这可能是不可行的。上述规则是一种务实的妥协。上面的最后一个子句要求总是将某些公共值装箱到不可区分的对象中。实现可能会懒洋洋地或急切地缓存这些。对于其他值,此公式不允许程序员对装箱值的同一性进行任何假设。这将允许(但不要求)共享一些或所有这些引用。

这确保了在大多数常见情况下,该行为将是所需的行为,而不会施加不适当的性能惩罚,特别是在小型设备上。例如,内存限制较少的实现可能html" target="_blank">缓存-32K到+32K范围内的所有char和short值以及int和long值。

 类似资料:
  • 问题内容: 我无法理解Java常量池常量的工作方式。 我了解字符串的行为,因此可以证明自己与整数常量也是如此。 所以,对于整数 和 直到这里一切都进入我的脑海。 我无法理解的是,当我从127增加整数时,它的行为有所不同。此行为在127之后发生变化,下面是代码段 有人可以帮我理解吗? 问题答案: 不,用于数字的常量池与用于字符串的方法不同。对于字符串,只保留编译时常量-而对于整数类型的包装器类型,如

  • 问题内容: 我到处都读到过,当您在Java中定义介于-128到127之间的Integer时,它不会创建新对象,而是返回已经创建的对象。 除了让新手程序员比较Integer对象以查看它们是否具有相同的数字外,我看不到这样做的任何意义,但是我认为这很糟糕,因为确保他们认为可以将任何Integer对象与进行比较,并且还在教学在任何编程语言中都不好的做法:将两个“不同”对象的内容与进行比较。 这样做有其他

  • 除了让新手程序员将整数对象与进行比较,以确定它们是否是相同的数字之外,我认为这样做没有什么意义,但我认为这是不好的,因为他们肯定认为可以将任何整数与进行比较,而且在任何编程语言中都教给了一种不好的做法:用比较两个“不同”对象的内容。 为什么这样做还有其他原因吗?或者这只是在设计语言时的一个错误决定(在我看来),就像JavaScript中的可选分号一样? 编辑:我在这里看到他们解释了行为:为什么整数

  • 问题内容: 关于我之前的问题,为什么与Integer.valueOf(String)进行==比较会得出127和128的不同结果?,我们知道Integer class有一个缓存用于存储-128和之间的值127。 只是想知道为什么在-128和127之间? Integer.valueOf()文档指出,它“ 缓存经常请求的值 ”。但是,-128和之间的值127是否经常被要求是真实的?我认为经常要求的价值观

  • 问题内容: 我知道整数在Java中是不可变的。但是为什么要这样设计呢? 我找不到强制Integer不可变的用例。是否有类似String的技术原因? 字符串在网络连接,数据库URL等中用作参数。如果它是可变的,则很容易遭到破坏。 支持StringPool功能。 支持使用字符串作为参数的类加载机制。字符串可变会导致加载错误的类。 我知道有些包装很易变。 更新: 从对话中,并没有普遍的理由要求整数是不可

  • 如果运行,将产生以下输出: 为什么当thread-0完成时,throwable-catching-activity似乎发生在这个完成的线程中?