Weird Integer Boxing in Java

Weird Integer boxing in Java

The true line is actually guaranteed by the language specification. From section 5.1.7:

If the value p being boxed is true,
false, a byte, a char in the range
\u0000 to \u007f, or an int or short
number between -128 and 127, then let
r1 and r2 be the results of any two
boxing conversions of p. It is always
the case that r1 == r2.

The discussion goes on, suggesting that although your second line of output is guaranteed, the first isn't (see the last paragraph quoted below):

Ideally, boxing a given primitive
value p, would always yield an
identical reference. In practice, this
may not be feasible using existing
implementation techniques. The rules
above are a pragmatic compromise. The
final clause above requires that
certain common values always be boxed
into indistinguishable objects. The
implementation may cache these, lazily
or eagerly.

For other values, this formulation
disallows any assumptions about the
identity of the boxed values on the
programmer's part. This would allow
(but not require) sharing of some or
all of these references.

This ensures that in most common
cases, the behavior will be the
desired one, without imposing an undue
performance penalty, especially on
small devices. Less memory-limited
implementations might, for example,
cache all characters and shorts, as
well as integers and longs in the
range of -32K - +32K.

When using == for a primitive and a boxed value, is autoboxing done, or is unboxing done

It is defined in the JLS #15.21.1:

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).

And JLS #5.6.2:

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

  • If any operand is of a reference type, it is subjected to unboxing conversion
    [...]

So to answer your question, the Integer is unboxed into an int.

Java Integer auto auto-boxing

Is this similar to String internalization?

Yes - essentially all integers that can fit in a byte (-128 to +127) are interned and thus share the same underlying object. Larger ones aren't, and thus probably don't share the same underlying object (this is covered in JLS 5.1.7) - though note that there's nothing in the spec that prevents larger integers sharing the same underlying object if someone were to choose to implement a VM that way.

I would imagine the rationale is that "smaller" integers in this range are used much more often than larger ones, so using the same underlying objects is worth it to reduce the potential memory footprint.

In your new Integer(100) == new Integer(100) example, this isn't the case since you're explicitly creating new integer objects, similar to how new String("hi") == new String("hi") evaluates to false.

Just to re-iterate - when comparing integers like this in all real world scenarios, then .equals() should be used (or preferably still, == with primitive integers unless there's a good case for using the object type.)

Does having a wrapper object return value (e.g. Integer) cause auto boxing in Java?

Yes, boxed

It will be (auto)boxed in the bytecode (.class file) because it's part of the public API, so other code might depend on the return value being an Integer.

The boxing and unboxing might be removed at runtime by the JITter under the right circumstances, but I don't know if it does that sort of thing.

Integer class object

This is due to an optimization in the virtual machine that maps small (frequently used) integers to a pool of objects that are reused. This answer explains some of the details.



Related Topics



Leave a reply



Submit