来自Effective Java的第9项(等于合同):示例是否正确?

前端之家收集整理的这篇文章主要介绍了来自Effective Java的第9项(等于合同):示例是否正确?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Bloch的精彩书籍“Effective Java”指出,如果equals不对称,那么Collections包含的行为是不确定的.

在他给出的例子中(通过下面的小修改再现),布洛赫说他看到了“假”,但也可以看到真实或异常.

如果标准没有指定contains(Object o)是否检查集合中每个项目的e.equals(o)或o.equals(e),并且实现前者,则可以看到“true”.然而,Collections Javadoc清楚地表明它必须是后者(这是我观察到的).

所以我看到的唯一可能性是“假”或可能是例外(但String Javadoc似乎排除了后者).

我理解更广泛的观点,非对称等于可能会导致集合之外的代码出现问题,但我不会在他引用的例子中看到它.

我错过了什么吗?

import java.util.List;
import java.util.ArrayList;

class CIString {
  private final String s;

  public CIString(String s) {
    this.s = s;
  }

  @Override public boolean equals( Object o ) {
    System.out.println("Calling CIString.equals from " + this.s );
    if ( o instanceof CIString) 
      return s.equalsIgnoreCase( ( (CIString) o).s);
    if ( o instanceof String) 
      return s.equalsIgnoreCase( (String) o );
    return false;
  }
  // Always override hashCode when you override equals
  // This is an awful hash function (everything collides -> performance is terrible!)
  // but it is semantically sound.  See Item 10 from Effective Java for more details.
  @Override public int hashCode() { return 42; }
}

public class CIS {
  public static void main(String[] args) {
   CIString a = new CIString("Polish");
   String s = "polish";

   List
最佳答案
这是一大早,所以也许我错过了你的问题的真正意义,这段代码将失败:

public class CIS 
{
    public static void main(String[] args) 
    {
        CIString a = new CIString("Polish");
        String s = "polish";

        List

至少你的代码找到它并且我的代码没有找到它是奇怪的(从理智的角度来看,这显然不是你的代码是如何编写的:-)

编辑:

public class CIS {
  public static void main(String[] args) {
   CIString a = new CIString("Polish");
   String s = "polish";

   List

现在代码打印出来:

list contains s:false
Calling CIString.equals from Polish
list contains a:true

这仍然没有意义……而且非常脆弱.如果两个对象像a.equals(b)那样相等,那么它们也必须等于b.equal(a),这与你的代码不同.

javadoc

It is symmetric: for any non-null reference values x and y,
x.equals(y) should return true if and only if y.equals(x) returns
true.

所以,是的,本书中的示例可能与集合API的Javadoc相反,但原则是正确的.不应该创建一个奇怪的行为或最终会出现问题的等于方法.

编辑2:

该文的关键点是:

In Sun’s current 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 run-time exception. Once
you’ve violated the equals contract,you simply don’t know how other
objects will behave when confronted with your object.

但是,鉴于Javadoc说它看起来似乎行为是固定的而不是实现工件.

如果它不在javadoc中,或者javadoc不是规范的一部分,那么它可能会在以后更改,代码将不再起作用.

猜你在找的Java相关文章