Symmetry—The second requirement says that any two objects must agree on
whether they are equal. Unlike the first requirement, it’s not hard to imagine vio-
lating this one unintentionally. For example, consider the following class, which
implements a case-insensitive string. The case of the string is preserved by
toString but ignored in comparisons:
// Broken - violates symmetry!
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
}
The well-intentioned equals method in this class naively attempts to interop-
erate with ordinary strings. Let’s suppose that we have one case-insensitive string
and one ordinary one:
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
As expected, cis.equals(s) returns true. The problem is that while the
equals method in CaseInsensitiveString knows about ordinary strings, the
equals method in String is oblivious to case-insensitive strings. Therefore
s.equals(cis) returns false, a clear violation of symmetry. Suppose you put a
case-insensitive string into a collection:
List<CaseInsensitiveString> list =
new ArrayList<CaseInsensitiveString>();
list.add(cis);
What does list.contains(s) return at this point? Who knows? In Sun’s cur-
rent implementation, it happens to return false, but that’s just an implementation
artifact. In another implementation, it could just as easily return true or throw a
runtime exception. Once you’ve violated the equals contract, you simply don’t
know how other objects will behave when confronted with your object.
To eliminate the problem, merely remove the ill-conceived attempt to interop-
erate with String from the equals method. Once you do this, you can refactor the
method to give it a single return:
@Override public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
这段话最后说改成的代码是
public final class CaseInsenstiveString { private final String s; public CaseInsenstiveString(String s) { if(s == null) { throw new NullPointerException(); } this.s = s; } @Override public boolean equals(Object o) { return o instanceof CaseInsenstiveString && ((CaseInsenstiveString) o).s.equalsIgnoreCase(s); } public static void main(String[] args) { CaseInsenstiveString cis = new CaseInsenstiveString("test"); String s = "test"; System.out.println(cis.equals(s)); System.out.println(s.equals(cis)); } }
测试结果,cis为Test还是test都是false
那么他这里的说法的意思是 根本不让CaseInsentiveString和String进行比较(因为o instanceof CaseInsenstiveString就是false了),即类型不同怎么比都false
还是有其他意思?
从对称性来看,是成立了,但是这样的例子怎么感觉不是说的这个意思,请大家指点