锁定老帖子 主题:Effective Java 第8条的疑问
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-06
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 还是有其他意思?
从对称性来看,是成立了,但是这样的例子怎么感觉不是说的这个意思,请大家指点 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 1543 次