The values of boxed primitives cannot be directly compared using the ==
and !=
operators because they compare object references, not object values. Programmers might 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.
...
If the value
p
being boxed istrue
,false
, abyte
, achar
in the range\u0000
to\u007f
, or anint
orshort
number between-128
and127
, then letr1
andr2
be the results of any two boxing conversions ofp
. It is always the case thatr1 == r2
.
Primitive Type | Boxed Type | Fully Memoized |
---|---|---|
|
| yes |
|
| no |
The ==
and !=
operators may be used to compare the values of fully memoized types.
The ==
and !=
operators must not may only be used for comparing the values of boxed primitives outside these specific casesthat are not fully memoized, when the range of values represented is guaranteed to be within the ranges specified by the JLS to be fully memoized.
In general, avoid using these operators to compare the values of boxed primitives that are not fully memoized.
Implementations are allowed, but not required, to memoizize values memoize additional values:
Less memory-limited implementations might, for example, cache all characters and shorts, as well as integers and longs in the range of -32K - +32K.
Code that depends on implementation-defined behavior is not portable.
Noncompliant Code Example
...
Code Block | ||
---|---|---|
| ||
public class Wrapper { public static void main(String[] args) { // Create an array list of integers, where each element // is greater than 127 ArrayList<Integer> list1 = new ArrayList<Integer>(); for (int i = 0; i < 10; i++) { list1.add(i + 1000); } // Create another array list of integers, where each element // has the same value as the first one ArrayList<Integer> list2 = new ArrayList<Integer>(); for (int i = 0; i < 10; i++) { list2.add(i + 1000); } // Count matching values int counter = 0; for(int i = 0; i < 10; i++) { if (list1.get(i).equals(list2.get(i))) { // uses 'equals()' counter++; } } // print the counter: 10 in this example System.out.println(counter); } } |
Exceptions
Noncompliant Code Example (new Boolean
)
Constructors for class Boolean
return distinct newly-instantiated objects. Using the reference equality operators in place of value comparisons will yield unexpected results.EXP03-EX1: The values of autoboxed Boolean
variables may be compared using the reference equality operators because the Java language guarantees that the autoboxing yields either Boolean.True
or Boolean.False
(as appropriate). These objects are guaranteed to be singletons.
Code Block | ||
---|---|---|
| ||
Boolean b1 = new Boolean("true; // Or Boolean.True"); Boolean b2 = new Boolean("true; // Or Boolean.True"); b1 == b2; // alwaysnever equal |
Compliant Solution (new Boolean
)
The values of autoboxed Boolean
variables may be compared using the reference equality operators because the Java language guarantees that the Boolean
type is fully memoized. Consequently, these objects are guaranteed to be singletonsNote, however, that the constructors for class Boolean
return distinct newly-instantiated objects. Using the reference equality operators in place of value comparisons will yield unexpected results in this case.
Code Block | ||
---|---|---|
| ||
Boolean b1 = new Boolean("true");true; // Or Boolean.True Boolean b2 = new Boolean("true"); true; // Or Boolean.True b1 == b2; // neveralways equal |
Exceptions
EXP03-EX1 In the unusual case where a program is guaranteed to execute only on a single implementation, it is permissible to depend upon implementation-specific ranges of memoized vulnerabilities.
Risk Assessment
Using the equivalence operators to compare values of boxed primitives can lead to erroneous comparisons.
...