The values of boxed primitives cannot be directly compared using the ==
and !=
operators because they these operators compare object references, not rather than object values. Programmers could find this behavior surprising because autoboxing memoizes, or caches, the values of some primitive variables. Consequently, reference comparisons and value comparisons produce identical results for the subset of values that are memoized.
...
Use of the ==
and !=
operators for comparing the values of boxed primitive types is forbidden in all other cases.This rule is a specialization of EXP01-J. Do not confuse abstract object equality with reference equality.
Note that JVM implementations are allowed, but not required, to memoize additional values:
...
This noncompliant code example uses the ==
operator in an attempt to compare two the values of pairs of Integer
objects. According to the rule, "EXP01-J. Do not confuse abstract object equality with reference equality," for However, the ==
operator to return true
for two object references, they must point to the same underlying objectcompares object references rather than object values.
Code Block | ||
---|---|---|
| ||
public class Wrapper { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 1000; Integer i4 = 1000; System.out.println(i1 == i2); System.out.println(i1 != i2); System.out.println(i3 == i4); System.out.println(i3 != i4); } } |
The Integer
class only caches is only guaranteed to cache integer values from -127
to 128
, which can result in equivalent values outside this range not comparing equalcomparing as unequal when tested using the equality operators. For example, a JVM that did not cache any other values when running this program would output
...
This compliant solution uses the equals()
method instead of the ==
operator to compare the values of the objects. The program now prints true
, false
, true
, false
on any platformall platforms, as expected.
Code Block | ||
---|---|---|
| ||
public class Wrapper { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 1000; Integer i4 = 1000; System.out.println(i1.equals(i2)); System.out.println(!i1.equals(i2)); System.out.println(i3.equals(i4)); System.out.println(!i3.equals(i4)); } } |
...
This noncompliant code example attempts to count the number of indices in arrays list1
and list2
that have equivalent values. Recall that class Integer
needs is required to memoize only those integer values in the range -127 to 128; it might return a non-unique objects object for all values any value outside that range. Consequently, when comparing autoboxed integer values outside that range, the ==
operator might return false
, and the output of this example might be 0.
...
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c51806889581e9ac-c35d0683-47654ab2-a0539a87-0ac207aacba99c0fb5e6885e"><ac:plain-text-body><![CDATA[ | [[Bloch 2009 | AA. Bibliography#Bloch 09]] | 4. "Searching for the One" | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="db06a8920c581799-c2c76157-422541c8-b9eb92d7-7c727e429d95d29cf93ad842"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. Bibliography#JLS 05]] | [§5.1.7, "Boxing Conversion" | http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="8346839beede414e-e8b5d249-46e64797-91c1bb9b-9889adc56334179d433104af"><ac:plain-text-body><![CDATA[ | [[Pugh 2009 | AA. Bibliography#Pugh 09]] | Using == to compare objects rather than .equals | ]]></ac:plain-text-body></ac:structured-macro> |
...