Why is this an issue?
The java.util.Collection
type and its subtypes provide methods to access and modify collections such as Collection.remove(Object
o)
and Collection.contains(Object o)
. Some of these methods accept arguments of type java.lang.Object
and will
compare said argument with objects already in the collection.
If the actual type of the argument is unrelated to the type of object contained in the collection, these methods will always return
false
, null
, or -1
. This behavior is most likely unintended and can be indicative of a design issue.
This rule raises an issue when the type of the argument provided to one of the following methods is unrelated to the type used for the collection
declaration:
-
Collection.remove(Object o)
-
Collection.removeAll(Collection<?>)
-
Collection.contains(Object o)
-
List.indexOf(Object o)
-
List.lastIndexOf(Object o)
-
Map.containsKey(Object key)
-
Map.containsValue(Object value)
-
Map.get(Object key)
-
Map.getOrDefault(Object key, V defaultValue)
-
Map.remove(Object key)
-
Map.remove(Object key, Object value)
How to fix it
Ask yourself what the purpose of this method call is. Check whether the provided argument and collection are correct in this context and for the
desired purpose. Remove unnecessary calls and otherwise provide an argument of which the type is compatible with the list content’s type.
Code examples
Noncompliant code example
void removeFromMap(Map<Integer, Object> map, String strKey) {
map.remove(strKey); // Noncompliant, this call will remove nothing and always return 'null' because 'map' is handling only Integer keys and String cannot be cast to Integer.
}
void listContains(List<String> list, Integer integer) {
if (list.contains(integer)) { // Noncompliant; always false as the list only contains Strings, not integers.
// ...
}
}
Compliant solution
void removeFromMap(Map<Integer, Object> map, String strKey) {
map.remove(Integer.parseInt(strKey)); // Compliant, strKey is parsed into an Integer before trying to remove it from the map.
}
void listContains(List<String> list, Integer integer) {
if (list.contains(integer.toString())) { // Compliant, 'integer' is converted to a String before checking if the list contains it.
// ...
}
}
Resources
- CERT, EXP04-J. - Do not pass arguments to certain Java Collections Framework methods
that are a different type than the collection parameter type
- Java SE 17 & JDK 17 - Collection
interface