为什么不在Java中缓存整数? [英] Why aren't Integers cached in Java?

查看:85
本文介绍了为什么不在Java中缓存整数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道类似的帖子这个话题,但他们并没有完全解决我的问题。当你这样做:

I know there are similar posts on the topic, but they don't quite address my question. When you do:

Integer a = 10;
Integer b = 10;
System.out.println("a == b: " + (a == b));

这将(显然)打印 true 大多数时间因为[-128,127]范围内的整数以某种方式被缓存。但是:

This will (apparently) print true most of the time because integers in the range [-128, 127] are somehow cached. But:

Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println("a == b: " + (a == b));

将返回 false 。我理解我要求Integer的新实例,但由于盒装原语在Java中是不可变的,并且机器已经在那里做正确的事情(如第一种情况所示),为什么会发生这种情况?

Will return false. I understand that I am asking for new instances of an Integer, but since boxed primitives are immutable in Java, and the machinery is already there to do the "right thing" (as seen in the first case), why does this happen?

如果一个带有10的Integer的所有实例都是内存中的同一个对象,那会不会更有意义?换句话说,为什么我们没有整数实习这类似于字符串实习?

Wouldn't it make more sense if all instances of an Integer with a 10 be the same object in memory? In other words, why don't we have "Integer interning" which would be similar to "String interning"?

更好的是,如果不是更有意义的话表示同一事物的盒装基元的实例,,无论值(和类型),是同一个对象吗?或者至少正确回应 ==

Better yet, wouldn't it make more sense if instances of a boxed primitive representing the same thing, regardless of value (and type), be the same object ? Or at least respond correctly to ==?

推荐答案

它应该是非常清楚,缓存具有令人无法接受的性能损失 - 每次创建Integer时都会发出额外的if语句和内存查找。仅此一点就掩盖了任何其他原因以及其余的痛苦。

It should be very clear that caching has an unacceptable performance hit -- an extra if statement and memory lookup every time you create an Integer. That alone overshadows any other reason and the rest of the agonizing on this thread.

至于正确回答==,OP在他的假设中是错误的正确性。整数DO通过一般Java社区对正确性的期望来正确地响应==,当然还有规范对正确性的定义。也就是说,如果两个引用指向同一个对象,则它们是 == 。如果两个引用指向不同的对象,则它们 == 即使它们具有相同的内容。因此, new Integer(5)== new Integer(5)的计算结果为 false 也就不足为奇了。

As far as responding "correctly" to ==, the OP is mistaken in his assumption of correctness. Integers DO respond correctly to == by the general Java community's expectation of correctness and of course by the specification's definition of correctness. That is, if two references point to the same object, they are ==. If two references point to different objects, they are not == even if they have the same contents. Thus, it should be no surprise that new Integer(5) == new Integer(5) evaluates to false.

更有趣的问题是为什么 新的Object(); 应该是必需的每次都创建一个独特的实例?一世。即为什么新的Object(); 不允许缓存?答案是 wait(...) notify(...)调用。缓存新的Object() s会错误地导致线程彼此同步。

The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.

如果它不是那样,那么Java实现可以用单例完全缓存 new Object()

If it were not for that, then Java implementations could totally cache new Object()s with a singleton.

这应解释为什么 new Integer(5)必须完成7次才能创建7个唯一的 Integer 对象,每个对象包含值5(因为整数 extends Object )。

And that should explain why new Integer(5) done 7 times must be required to create 7 unique Integer objects each containing the value 5 (because Integer extends Object).

次要,不太重要的东西:这个不错的方案中的一个问题来自自动装箱和自动装箱功能。没有该功能,您无法进行比较,例如 new Integer(5)== 5 。要启用这些,Java 取消装箱该对象(并且框)该原语。因此 new Integer(5)== 5 转换为: new Integer(5).intValue()== 5 (和 new Integer(5)== new Integer(5)

Secondary, Less Important Stuff: One problem in this otherwise nice scheme results from the autoboxing and autounboxing feature. Without the feature you could not do comparisons such as new Integer(5) == 5. To enable these, Java unboxes the object (and does not box the primitive). Therefore new Integer(5) == 5 is converted to: new Integer(5).intValue() == 5 (and not new Integer(5) == new Integer(5).

最后要明白的一点是 n 的自动装箱是新的整数(n)。通过调用 Integer.valueOf(n)在内部完成。

One last thing to understand is that autoboxing of n is not done by new Integer(n). It is done internally by a call to Integer.valueOf(n).

如果你认为你理解并想测试自己,预测以下程序的输出:

If you think you understand and want to test yourself, predict the output of the following program:

public class Foo {
  public static void main (String[] args) {
    System.out.println(Integer.valueOf(5000) == Integer.valueOf(5000));
    System.out.println(Integer.valueOf(5000) == new Integer(5000));
    System.out.println(Integer.valueOf(5000) == 5000);
    System.out.println(new Integer(5000) == Integer.valueOf(5000));
    System.out.println(new Integer(5000) == new Integer(5000));
    System.out.println(new Integer(5000) == 5000);
    System.out.println(5000 == Integer.valueOf(5000));
    System.out.println(5000 == new Integer(5000));
    System.out.println(5000 == 5000);
    System.out.println("=====");
    System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
    System.out.println(Integer.valueOf(5) == new Integer(5));
    System.out.println(Integer.valueOf(5) == 5);
    System.out.println(new Integer(5) == Integer.valueOf(5));
    System.out.println(new Integer(5) == new Integer(5));
    System.out.println(new Integer(5) == 5);
    System.out.println(5 == Integer.valueOf(5));
    System.out.println(5 == new Integer(5));
    System.out.println(5 == 5);
    System.out.println("=====");
    test(5000, 5000);
    test(5, 5);
  }
  public static void test (Integer a, Integer b) {
    System.out.println(a == b);
  }
}

如需额外信用,还可预测输出 == 更改为 .equals(...)

For extra credit, also predict the output if all the == are changed to .equals(...)

更新:感谢用户@sactiw的评论:默认的缓存范围是-128到127和java 1.6以后你可以通过传递-XX来重置上限值> = 127:AutoBoxCacheMax =从命令行

Update: Thanks to comment from user @sactiw : "default range of cache is -128 to 127 and java 1.6 onward you can reset the upper value >=127 by passing -XX:AutoBoxCacheMax= from command line"

这篇关于为什么不在Java中缓存整数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆