我正在学习Effective Java,第8项(在覆盖equals时遵守一般合同)。作者已经非常清楚地解释了这一点,但仍有一些部分没有详细阐述。
对于这个例子,他认为一个CaseInsensitiveString类定义为:
public final class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
// Broken - violates symmetry!
@Override
public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString)
return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
if (o instanceof String) // One-way interoperability!
return s.equalsIgnoreCase((String) o);
return false;
}
// ... // Remainder omitted
}
在文章的最后,他说:
对于某些类,例如上面的CaseInsensitiveString,字段比较 比简单的相等测试更复杂。如果是这种情况,您可能需要 存储一个规范形式的字段,所以equals方法可以做得很便宜 比较这些规范形式而不是更昂贵的不精确比较 isons。这种技术最适用于不可变类(第15项);如果 对象可以更改,您必须使规范形式保持最新。
我搜索了这个术语,发现它基本上意味着某种东西的标准表示,比如绝对路径,没有任何目录中文件的符号链接。但是我无法理解在这个课程中使用“规范”形式,这在这里会有所帮助。有什么建议吗?
答案 0 :(得分:7)
我认为在这个特定的例子中,规范形式可能存储字符串的小写或大写版本并对其进行比较。
private final String s;
public CaseInsensitiveString(String s) {
//for real code probably use locale version
this.s = s.toLowerCase();
}
这使得相等比较更便宜,因为我们可以进行精确的字符串比较而不是更昂贵的equalsIgnoreCase
// Broken - violates symmetry!
@Override
public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString)
return s.equals(((CaseInsensitiveString) o).s);
if (o instanceof String) // One-way interoperability!
return s.equals((String) o);
return false;
}