字段的规范形式

Canonical form of field

我正在研究 Effective Java,第 8 项(在重写 equals 时遵守一般合同)。作者已经解释的很清楚了,但是还是有些地方没有那么详细。

对于这个例子,他认为 class 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
}

在文章的最后,他说:

For some classes, such as CaseInsensitiveString above, field comparisons are more complex than simple equality tests. If this is the case, you may want to store a canonical form of the field, so the equals method can do cheap exact comparisons on these canonical forms rather than more costly inexact compar- isons. This technique is most appropriate for immutable classes (Item 15); if the object can change, you must keep the canonical form up to date.

我搜索了这个词,发现它基本上是指某物的标准表示,例如目录中文件的绝对路径,没有任何符号链接。但是我无法理解 'canonical' 形式用于此 class 的用法,这对这里有帮助。有什么建议吗?

我认为在这个特定示例中,规范形式可能会存储字符串的小写或大写版本并对其进行比较。

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;
}