【问题标题】:Overriden equals and hashcode methods of superclass. Do I do for subclass覆盖超类的 equals 和 hashcode 方法。我为子类做吗
【发布时间】:2011-12-13 00:32:20
【问题描述】:

我有一个包含 2 个实例变量的超类(比如 int aint b)和 现在决定我需要在我的子类int c 中有一个实例变量。

我已经覆盖了超类的 equals 和 hashCode 方法来考虑 对象/值的平等。我还覆盖了超类 toString 以提供一个字符串 表示对象的状态(变量值)。

基于以上事实,我现在在我的子类中有一个实例变量 int c 我想知道我是否

  1. 需要重写子类中的 toString 方法,还是因为我在超类中有一个有效的可继承 toString 方法(已经被重写),可用于子类字符串表示?
  2. 需要重写子类中的equals方法。可以这样做吗 通过调用超类的equals方法并在调用后为我的子类实例变量添加比较代码,还是需要新的实现?我认为是后者?
  3. 我打算重写子类中的 hashCode 方法。同样,最好有一个新的实现而不是调用超类的 hashCode 方法?我本来打算 将子类 equals 方法中的 a、b 和 c 与另一个对象进行比较,并在子类 hashCode 方法中为 a b 和 c 创建哈希码?这是要走的路还是需要我只考虑子类 equals 和 hashcode 方法中的变量 c?

我查看了各种资源,包括 bloch 撰写的 Effective Java(第 3 章),但找不到上述问题的答案

【问题讨论】:

    标签: java hash equals


    【解决方案1】:

    此答案假设您的班级如下所示:

    public class MySuperClass {
        int a,b;
    }
    
    public class MySubClass extends MySuperClass {
        int b;
    }
    

    首先,您的 cmets re toString() 与主要问题无关。在任何情况下,您的代码都不应该依赖 toString 实现——它的输出仅供人类使用。不过可以随意使用 super impl:

    public String toString() {
        return super.toString() + ", c=" + c;
    }
    

    其次,equals() 应该比较对象的(已发布)状态。由于子类有另一个字段,它需要自己的equals()。但是,您也许可以使用超类的equals() 方法,如下所示:

    public boolean equals(Object o) {
        // The super equals() will compare int a and int b for us
        if (!super.equals(o)) {
             return false;
        }
        // super thinks it is equal, so let's compare int c
        return o instanceof MySubClass && ((MySubClass)o).c == c;
    }
    

    第三,hashcode 应该与 equals 对齐,所以也要实现它。同样,你可以使用 super 的 impl 来对 a 和 b 进行哈希处理:

    public int hashcode() {
        return super.hashcode() + new Integer(c).hashCode(); // for example
    }
    

    【讨论】:

    • 您的 equals 方法违反了 Object.equals 规定的对称属性,可能不应该使用。 superclass.equals(subclass) 将返回 true,而 subclass.equals(superclass) 将返回 false。
    • 您可以将new Integer(c).hashCode() 替换为c
    【解决方案2】:

    只要子类中的所有内容都存在于超类中,就无需覆盖它们(当然,除非您想要一些不同的功能)。

    基本上,仅当您希望每个子类具有不同的功能时才重写该方法。

    当然,您说您的子类有一个新变量int c。在这种情况下,您需要重写该方法以获得完整的功能,尤其是对于 equals()hashCode()

    【讨论】:

      【解决方案3】:

      这取决于您要表示的内容,以及您的 equalshashCode 方法当前执行的操作。除非您希望将子类添加的新字段考虑在内,否则您不需要严格重写, 如果您的超类方法对扩展类的可能性不可靠(例如,比较 obj.getClass() 而不是使用 instanceof)。

      【讨论】:

        【解决方案4】:

        如果要正确表示对象的哈希,则需要同时覆盖equals和hashCode。如果您不覆盖 hashCode() 则仅因新字段 c 的差异而变化的对象将全部放入同一个哈希桶中(如果您覆盖 hashCode 那么您必须覆盖 equals 因为两个相等的对象必须具有相同的散列)。您的 hashCode 实现可以利用超类实现并将其添加到附加的子类字段中。

        不幸的是,不可能为一个非抽象类的子类化并为其添加新字段的类编写严格正确的 equals 函数。你要么最终破坏了 equals 的一些约定属性,要么使只添加方法的子类也最终变得不相等。

        建议的解决方法是不要子类化以添加字段,而是创建一个复合类,其中包含父类和新字段的实例,并导出包含的视图类,以便在需要时进行比较。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-05
          • 1970-01-01
          • 2020-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-09
          相关资源
          最近更新 更多