4

我试图了解 Java 原语和包装器是如何工作的。让我们考虑下面的例子。

Integer sum = 0;
for(int i = 0; i < 10000; ++i) {
    sum += i;
}

由于 Integer 是不可变且非原始的,因此该语句sum += i将编译为以下

sum =  new Integer(sum.intValue() + i).

这将创建大约 10000 个 Integer 对象(每次调用 new )以及将 Integer 拆箱为 intInteger的成本。sum.intValue()

我对吗?

4

4 回答 4

6

Not exactly. In fact:

    sum += i;

is equivalent to

    sum = Integer.valueOf(sum.intValue() + i);

For small integer values, Integer.valueOf(int) will return a cached Integer object. That means that you will get somewhat less than 10,000 new Integer objects created.

But "small" typically means -128 to +127 (IIRC) ... so the difference won't be significant.


As Louis Wasserman points out,object allocation is cheap, and garbage collection of objects that "die young" is even cheaper. Nevertheless, you shouldn't use primitive wrappers unnecessarily, and especially not in code like this.

于 2013-08-29T05:09:23.430 回答
2

No it's not like that. The compound assignment operator E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), with the difference that E1 is only evaluated once.

From JLS Section 15.26.2:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

So, a binary operation is performed between an Integer reference and a primitive type. In which case, the Integer reference will be unboxed, and operation will be performed, and value will again be boxed to Integer reference. As from JLS Section 5.6.2 - Binary Numeric Promotion:

If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).

So, no a new Integer object is not necessarily created. The expression in your loop is evaluated as:

Integer sum = Integer.valueOf(sum.intValue() + i);

And the valueOf method may use some cached value of Integer object(for some range).


Having said all that, I hope you are not literally using a wrapper type like that in your original code, but just for the understanding purpose. You don't need to use wrapper type, unless you really need it, and that would be rare case.

于 2013-08-29T05:09:07.853 回答
2

使用 Loop 时首选原始类型而不是盒装类型

是的,您是正确的装箱和拆箱过程,尤其是在循环中会严重阻碍性能。

但在你的情况下,你只是在循环,你应该在这里使用盒装原语,而是使用int

于 2013-08-29T05:10:52.497 回答
1

是的,差不多 10000。这是一个 decomiled .class

    Integer sum = Integer.valueOf(0);
    for(int i = 0; i < 10000; i++)
        sum = Integer.valueOf(sum.intValue() + i);

Integer.valueOf 对小数有缓存,默认 -128 到 127,所以实际上会创建 10000 - 128 个 Integer 实例

于 2013-08-29T05:14:57.573 回答