【Effective Java 10.2】覆盖 equals 时请遵守通用约定 —— 对称性
作者:互联网
任何两个对象对于 “它们是否相等” 问题必须保持一致。与第一个要求不同,若无意中违反这一条,这种情形倒是不难想象。例如,下面的类,它实现了一个不区分大小写的字符串。字符串由 toString
保存,但在 equals
操作中被忽略。
/**
* 覆写 Object 的 equals 方法时, 必须满足对称性要求 (Symmetry)
* 即 x.equals(y) 与 y.equals(x) 的行为必须一致
* <p>
* 下面展示了一个违反该约定的情况
* 一旦违反了 equals 约定, 当其他对象面对你的对象时, 你完全不知道这些对象的行为会怎样.
*/
public class SymmetryBadDemo {
public static final class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s) {
this.s = s;
}
/**
* 这里的 equals 方法存在一个漏洞
* 就是一个 CaseInsensitiveString 对象和一个 String 对象比较的时候会出现问题
* 造成这一现象的原因主要是
*/
@Override
public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString) {
return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
}
if (o instanceof String) {
return s.equalsIgnoreCase(((String) o));
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(s.toLowerCase());
}
}
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
System.out.println("违反自反性的例子");
System.out.println("cis.equals(s) = " + cis.equals(s));
System.out.println("s.equals(cis) = " + s.equals(cis));
}
}
为了解决这个问题,是需要禁止 String
与 CaseInsensitiveString
之间的互操作即可。
public class SymmetryGoodDemo {
public static final class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s) {
this.s = s;
}
/**
* 解决方法: 禁止与 String 类型的对象互操作
* 由于 CaseInsensitiveString 与 String 之间没有任何继承关系.
* 而 equals 函数输入的是一个 Object 对象
* 要避免 CaseInsensitiveString 与 String 之间进行比较
* 就要在 equals 中主动判断 Object 对象的实际类型与当前类的类型是否一致
*/
@Override
public boolean equals(Object o) {
return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
@Override
public int hashCode() {
return Objects.hash(s.toLowerCase());
}
}
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
System.out.println("遵守自反性的修改");
System.out.println("cis.equals(s) = " + cis.equals(s));
System.out.println("s.equals(cis) = " + s.equals(cis));
}
}
标签:CaseInsensitiveString,10.2,Java,String,Effective,equals,cis,return,public 来源: https://www.cnblogs.com/Silgm/p/16069203.html