...
Wiki Markup |
---|
This noncompliant code example (adopted from \[[Bloch 09|AA. Java References#Bloch 09]\]), defines a {{Comparator}} with a {{compare()}} method. The {{compare()}} method accepts two boxed primitives as arguments. Note that primitive integers are also accepted by this declaration as they are appropriately autoboxed. The main issue is that the {{==}} operator is being used to compare the two boxed primitives. ThisHowever, however,this compares their references and not the actual values. |
...
To be compliant, use any of the four comparison operators <
, >
, <=
and >=
. The ==
and !=
operators should not be used to compare boxed primitives.
...
Code Block | ||
---|---|---|
| ||
public class TestWrapper2 { 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); } } |
These comparisons generate the output sequence: true
, false
, false
and true
. The cache
in the Integer
class can only make the integers from -127
to 128
refer to the same object, which explains the output of the above code. To avoid making such mistakes, use the equals()
method instead of ==
to compare wrapper classes (See EXP03-J for further details).
...
Using object1.equals(object2) only compares their the values of the objects. Now, the results will be true
, as expected.
...
Sometimes a list of integers is desired. Recall that the type parameter inside the angle brackets of a list cannot be of a primitive type. It is not possible to form an ArrayList<int>
that contains values of type int
. With the help of the wrapper classs classes and autoboxing, storing primitive it becomes possible to store integer values in an ArrayList<Integer>
becomes possible instance.
In this noncompliant code example, it is desired to count the integers of arrays list1
and list2
. As class Integer
only caches integers from -127 to 128, when an int
value is beyond this range, it is autoboxed into the corresponding wrapper type. The ==
operator returns false
when these distinct wrapper objects are compared. As a result, the output of this example is 0.
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 < 10; i++) { list1.add(i + 1000); } // Create another array list of integers, where each element // is the same as the first list ArrayList<Integer> list2 = new ArrayList<Integer>(); for(int i = 0;i<10; i < 10; i++) { list2.add(i + 1000); } int counter = 0; for(int i = 0;i<10; i < 10; i++) { if(list1.get(i) == list2.get(i)) { counter++; } } // print the counter System.out.println(counter); } } |
If it were possible to expand the Integer
cache (for example, caching all the values -32K – 32K32768 to 32767, which means that all the int
values in the example would be autoboxed to cached Integer
objects), then the results may have differed.
...
Code Block | ||
---|---|---|
| ||
public class TestWrapper1 { 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 < 10; i++) { list1.add(i+1000); } // Create another array list of integers, where each element // is the same as the first one ArrayList<Integer> list2 = new ArrayList<Integer>(); for(int i=0;i<10;i++) { list2.add(i+1000); } int counter = 0; for(int i=0;i<10;i++) { if(list1.get(i).equals(list2.get(i))) { counter++; } } System.out.println(counter); } } |
...