I want to write a method which takes a collection as a parameter. However, the collection cannot contain null. If it contains null, this will lead to a NullPointerException later on, when it is not clear anymore where the null came from. Therefore, I want to validate the input. The naive approach would be:
public void doSomething(Collection<?> collection) {
if (collection.contains(null))
throw new IllegalArgumentException("collection cannot contain null!");
// do something
}
However, Collection.contains may throw a NullPointerException if the collection does not support null values. In fact, Java's own immutable collections do that. So, in the naive approach, the following code does not work:
doSomething(List.of("a", "b", "c")); // NullPointerException!
There are a few possible solutions, but none of them feel right.
For example, I could search for null myself:
public void doSomething(Collection<?> collection) {
for (var e : collection) {
if (e == null)
throw new IllegalArgumentException("collection cannot contain null!");
}
// do something
}
But now I'm doing a linear search, although the collection might be a HashSet or a TreeSet, offering much better performance.
Or I could catch the NullPointerException:
public void doSomething(Collection<?> collection) {
try {
if (collection.contains(null))
throw new IllegalArgumentException("collection cannot contain null!");
} catch (NullPointerException e) {
// Apparently, collection doesn't support null. This is good!
}
// do something
}
But this feels very unsafe. Can I really be sure that that NullPointerException was caused by the collection not supporting nulls, or did I just eat an Exception which could provide valuable information on a bug?
Is there a good way to determine whether a collection contains null?