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
Trying to Locate a Leak! What Does Anon Mean for Pmap
Running Java Program from Command Line Linux
How to Troubleshoot "Inconsistency Detected: Dl-Lookup.C: 111" (Java Result 127) Error
Javafx Freeze on Desktop.Open(File), Desktop.Browse(Uri)
How to View/Change Socket Connection Timeout on Linux
Can't Make Jdbc Connection to MySQL (Using Java, Intellij, and Linux)
Inputstream.Available() Is 0 Always
How to Achieve Javafx Mouse Event "Push and Hold"
Installing Oracle Jdk on Windows Subsystem for Linux
Linux Command for Extracting War File
How to Debug Java -Jni Using Gdb on Linux
When Exactly Do You Use the Volatile Keyword in Java
Should One Call .Close() on Httpservletresponse.Getoutputstream()/.Getwriter()
How to Write Console Output to a Txt File
Gradle Does Not Find Tools.Jar
How to Convert the Following JSON String to Java Object
Jersey /* Servlet Mapping Causes 404 Error for Static Resources