I'm studying Effective Java, Item 8 (Obey the general contract when overriding equals). It has been explained quite clearly by the author, but still some parts are not that much elaborated.
For this example, he considers a class CaseInsensitiveString defined as :
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
}
In the end of the article, he says :
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.
I searched for this term and found that it basically means a standard representation of something, like absolute path without any symbolic links for a file in a directory. But I'm unable to understand the use of 'canonical' form for this class, which would help here. Any suggestions?