CodeQL 文档

从抽象集合转换为具体集合

ID: java/abstract-to-concrete-cast
Kind: problem
Security severity: 
Severity: warning
Precision: very-high
Tags:
   - reliability
   - maintainability
   - modularity
   - external/cwe/cwe-485
Query suites:
   - java-security-and-quality.qls

单击以在 CodeQL 存储库中查看查询

Java 标准库中的大多数集合都由抽象接口(例如 java.util.Listjava.util.Set)定义,该接口由一系列具体类和一系列包装器实现。通常,除了构造对象时,最好使用抽象类型,因为这避免了对实现方式的假设。

从抽象集合转换为具体集合会使代码变得脆弱,因为它确保代码仅适用于一个可能的实现类,而不适用于其他类。通常,此类转换要么表明过度依赖具体实现类型,要么表明使用了错误的抽象类型。

建议

通常最好在变量、字段和参数声明中始终如一地使用抽象类型。

可能会有个别例外。例如,当迭代顺序很重要并且只有 LinkedHashSet 实现提供正确行为时,通常将变量声明为 LinkedHashSet 而不是 Set

示例

以下示例说明了使用错误抽象类型的情况。 List 接口不提供 poll 方法,因此原始代码将 queue 转换为提供此方法的具体类型 LinkedList。若要避免这种向下转换,只需为此方法使用正确的抽象类型,即 Queue。这记录了程序员的意图,并允许此方法的客户端使用各种队列实现。

Customer getNext(List<Customer> queue) {
	if (queue == null)
		return null;
	LinkedList<Customer> myQueue = (LinkedList<Customer>)queue;  // AVOID: Cast to concrete type.
	return myQueue.poll();
}

Customer getNext(Queue<Customer> queue) {
	if (queue == null)
		return null;
	return queue.poll();  // GOOD: Use abstract type.
}

参考

  • J. Bloch,Effective Java(第二版),第 52 条。Addison-Wesley,2008 年。

  • Java API 规范:Collection

  • 常见弱点枚举:CWE-485

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