Java 5 added various overloaded checkedXYZ() methods in java.util.Collections class which return a corresponding dynamically typesafe collection. The new returned collection wraps the user specified collection and add some additional runtime checks to avoid wrong type to be inserted/added to the collection.
From Java docs
The generics mechanism in the language provides compile-time (static) type checking, but it is possible to defeat this mechanism with unchecked casts. Usually this is not a problem, as the compiler issues warnings on all such unchecked operations. There are, however, times when static type checking alone is not sufficient. For example, suppose a collection is passed to a third-party library and it is imperative that the library code not corrupt the collection by inserting an element of the wrong type.
Following is the one of the methods from this group:
public static <E> List<E> checkedList(List<E> list, Class<E> type)
Let's understand the advantage of using these methods with an example.
Example
Let's say we have a third party library util method which supposed to square all integers elements of the provided list.
public class NotMyUtil {
@SuppressWarnings("unchecked")
public static void squared(List<Integer> list) {
list.replaceAll(i -> Math.multiplyExact(i, i));
List myList = list;
myList.add("aString");
}
}
The above method has a bug in it, it's adding a string element after unchecked assignment. Let's assume we don't know about the bug and use the method:
public class CollectionExample {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 4, 5));
NotMyUtil.squared(list);
IntStream intStream = list.stream()
.mapToInt(Integer::intValue);
int sum = intStream.sum();
System.out.println(sum);
}
} OutputCaused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at java.util.stream.ReferencePipeline$4$1.accept(ReferencePipeline.java:210) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.IntPipeline.reduce(IntPipeline.java:456) at java.util.stream.IntPipeline.sum(IntPipeline.java:414) at com.logicbig.example.CollectionExample.main(CollectionExample.java:15) ... 6 more
The stack trace shows the exception is originating from our main class at the point where we are getting sum from inStream.
at com.logicbig.example.CollectionExample.main(CollectionExample.java:15)
Let's use Collections.checkedList now:
public class TypeSafeCheckedCollectionExample {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 4, 5));
list = Collections.checkedList(list, Integer.class);
NotMyUtil.squared(list);
IntStream intStream = list.stream()
.mapToInt(Integer::intValue);
int sum = intStream.sum();
System.out.println(sum);
}
} OutputCaused by: java.lang.ClassCastException: Attempt to insert class java.lang.String element into collection with element type class java.lang.Integer at java.util.Collections$CheckedCollection.typeCheck(Collections.java:3037) at java.util.Collections$CheckedCollection.add(Collections.java:3080) at com.logicbig.example.NotMyUtil.squared(NotMyUtil.java:11) at com.logicbig.example.TypeSafeCheckedCollectionExample.main(TypeSafeCheckedCollectionExample.java:14) ... 6 more
This time the exception is thrown at the right place, our checkList doesn't allow to add wrong type in it:
at com.logicbig.example.NotMyUtil.squared(NotMyUtil.java:11)
In scenarios like above, by using Collections checkedXYZ methods, we can detect the problem way earlier.
Other checkedXYZ methods
Followings are the all Collections.checkedXYZ methods:
static <E> Collection<E> checkedCollection(Collection<E> c,
Class<E> type) static <E> Set<E> checkedSet(Set<E> s,
Class<E> type) static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
Class<E> type) static <E> List<E> checkedList(List<E> list,
Class<E> type) static <K,V> Map<K,V> checkedMap(Map<K,V> m,
Class<K> keyType,
Class<V> valueType) static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K,V> m,
Class<K> keyType,
Class<V> valueType) |
Example ProjectDependencies and Technologies Used:
|