Equals 方法不检查参数类型¶
ID: java/unchecked-cast-in-equals
Kind: problem
Security severity:
Severity: error
Precision: high
Tags:
- reliability
- correctness
Query suites:
- java-security-and-quality.qls
为了避免失败的转换,equals 的实现必须能够处理任何类型的参数。因此,实现应检查其参数的类型,以查看参数是否可以安全地转换为声明 equals 方法的类。
建议¶
通常,equals 的实现应使用 instanceof 检查其参数的类型,遵循以下一般模式。
class A {
// ...
public final boolean equals(Object obj) {
if (!(obj instanceof A)) {
return false;
}
A a = (A)obj;
// ...further checks...
}
// ...
}
以这种方式使用 instanceof 的好处在于,它包括防止空指针异常的保护:如果 obj 为 null,则检查失败并返回 false。因此,在检查之后,可以保证 obj 不为 null,并且可以安全地访问其字段。
每当使用 instanceof 检查参数类型时,应将 equals 方法声明为 final,这样子类将无法通过进一步覆盖 equals 来导致违反 equals 契约的对称性要求。
如果您希望子类通过覆盖 equals 来重新定义相等性的概念,请使用 getClass 而不是 instanceof 来检查参数类型。但是,请注意,使用 getClass 会阻止类实例与其子类之间的任何相等性关系,即使子类中没有添加任何其他状态也是如此。
参考¶
J. Bloch,Effective Java(第二版),第 8 项。Addison-Wesley,2008 年。
Java API 规范:Object.equals()。
Java 语言规范:类型比较运算符 instanceof。