Integer Wrapper Class and == Operator - Where Is Behavior Specified

Integer wrapper class and == operator - where is behavior specified?

Because of this code in Integer.valueOf(int):

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

Explanation:

Integer integer1 = 127 is a shortcut for Integer integer1 = Integer.valueOf(127), and for values between -128 and 127 (inclusive), the Integers are put in a cache and returned multiple times, while higher and lower numbers generate new Integers each time.

operator == differet behaviour on wrapper class object

The == comparator checks for object equality!

Since Integer.valueOf maintains a cache of Integer Objects with the value -128 to 127 valueOf(String) returns the cached object, thus the == comparance results in true.

Integer a1 = new Integer("12");
Integer b1 = new Integer("12");
//a1 == b1 returns false because they point to two different Integer objects

Integer aa = Integer.valueOf("12");
Integer bb = Integer.valueOf("12");
//aa == bb returns true because they point to same cached object

For the comparance of object values always use the .equals method, for primitives like int, long etc. you can use the == comparator.

Using == operator in Java to compare wrapper objects

The key to the answer is called object interning. Java interns small numbers (less than 128), so all instances of Integer(n) with n in the interned range are the same. Numbers greater than or equal to 128 are not interned, hence Integer(1000) objects are not equal to each other.

Why does post-increment work on wrapper classes

It's perfectly safe to use across platforms. The behavior is specified in §15.4.2 of the Java Language Specification (emphasis added):

The result of the postfix expression must be a variable of a type that is convertible (§5.1.8) to a numeric type, or a compile-time error occurs.

The type of the postfix increment expression is the type of the variable. The result of the postfix increment expression is not a variable, but a value.

At run-time, if evaluation of the operand expression completes abruptly, then the postfix increment expression completes abruptly for the same reason and no incrementation occurs. Otherwise, the value 1 is added to the value of the variable and the sum is stored back into the variable. Before the addition, binary numeric promotion (§5.6.2) is performed on the value 1 and the value of the variable. If necessary, the sum is narrowed by a narrowing primitive conversion (§5.1.3) and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored. The value of the postfix increment expression is the value of the variable before the new value is stored.

EDIT Here's a more accurate equivalent of what's going on in your example code:

Integer x = 0;
int temp = x.intValue();
x = temp + 1; // autoboxing!
System.out.println(temp + ", ");
System.out.println(x.intValue());

Why does ' ', ' ' work with wrapper classes while '==' doesn't ?

The <, >, <= and >= operators are only defined for primitive types. Therefore using them on wrapper types causes the compiler to unbox the objects into primitives.

This means

System.out.println(a>=b);

is equivalent to

System.out.println(a.intValue()>=b.intValue());

However, the == and != operators exist for both primitive types and reference types, so using them to compare two objects of primitive wrapper types compares the references instead of the primitive values they wrap.

As Holger commented, comparison of object references with == and != existed in the Java language before auto-boxing and auto-unboxing were introduced, but comparison with <, >, <= and >= was not supported for any reference types before auto-unboxing was introduced.

This means that in the early days of Java, the a>=b of your code snippet would not pass compilation (since a and b are not primitive numeric types). On the other hand your a==b snippet would still pass compilation and return false.

Changing the behavior of == and != for reference types that happen to be wrappers of numeric primitives would change the behavior of existing code, thus breaking backwards compatibility, which is probably the reason it wasn't done.



Related Topics



Leave a reply



Submit