CodeQL 文档

容器修改类型不匹配

ID: java/type-mismatch-modification
Kind: problem
Security severity: 
Severity: error
Precision: very-high
Tags:
   - reliability
   - correctness
   - logic
Query suites:
   - java-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

Collection 接口的 remove 方法有一个类型为 Object 的参数。因此,您可以尝试从集合中删除任何类型的对象,而不管集合的元素类型。但是,尽管您可以使用与集合不同的类型的参数调用 remove,但该集合不太可能实际包含这种类型的对象。

类似的考虑适用于其他容器修改方法,例如 Map.remove,其中参数也可能具有类型 Object

建议

确保您在调用 remove 时使用正确的参数。

示例

在以下示例中,虽然 contains 的参数是整数,但代码不会导致类型错误,因为 remove 的参数不必与 list 元素的类型匹配。但是,该参数不太可能被找到并删除(因此 if 语句的主体不会执行),所以它可能是一个拼写错误:该参数应该用引号括起来。

void m(List<String> list) {
	if (list.remove(123)) {  // Call 'remove' with non-string argument (without quotation marks)
		// ...
	}
}

请注意,在处理装箱类型集合时,您必须格外小心,如下面的示例所示。第一次调用 remove 失败,因为您不能比较两个不同类型的装箱数值基本类型,在本例中是 Short(1)(在 set 中)和 Integer(1)(参数)。因此,remove 无法找到要删除的项。第二次调用 remove 成功,因为您可以比较 Short(1)Short(1)。因此,remove 可以找到要删除的项。

HashSet<Short> set = new HashSet<Short>();
short s = 1;
set.add(s);
// Following statement fails, because the argument is a literal int, which is auto-boxed 
// to an Integer
set.remove(1);
System.out.println(set); // Prints [1]
// Following statement succeeds, because the argument is a literal int that is cast to a short, 
// which is auto-boxed to a Short
set.remove((short)1);
System.out.println(set); // Prints []

参考文献

  • ©GitHub, Inc.
  • 条款
  • 隐私