【问题标题】:Why doesn't class ProcessBuilder override equals()?为什么类 ProcessBuilder 不覆盖 equals()?
【发布时间】:2013-07-05 00:42:11
【问题描述】:

我最近发现 JDK6 中的 ProcessBuilder 类不会覆盖 equals()。有原因吗?由于类是可变的,我可以理解为什么它不覆盖hashCode()

看到这段代码不起作用,我很惊讶:

ProcessBuilder x = new ProcessBuilder("abc", "def");
ProcessBuilder y = new ProcessBuilder("abc", "def");
if (x.equals(y)) {  // they are never equal
    // something important here
}

我查看了 ProcessBuilder 类的 JDK6 源代码,但没有看到 equals() 的覆盖。

我有一种感觉,除了这一门课之外,还有更深层次的原因。也许这是故意的?

【问题讨论】:

    标签: java jdk6


    【解决方案1】:

    补充@PeterLawrey 的回答:对于本质上可变的对象,实现equals 和hashcode 在任何情况下都是有风险的。您根本无法保证此类对象会安全发布。因此,此类类的作者只是“放弃”此类类的 equals 和 hashcode 是有道理的。

    但是:如果您有理由确定您可以控制这种平等,那么您有一些东西:Guava's Equivalence。如果您可以确保对高度可变类的充分控制访问,这允许您为此类对象定义相等/哈希码策略,以便您甚至可以在例如HashSet 中使用它们。

    更多关于Equivalence:对于本质上可变的“不稳定”类X,但您可以保证在给定上下文中的等价性,您可以实现Equivalence<X>。然后你将X 的这些实例“包装”到例如a:

    Set<Equivalence.Wrapper<X>>
    

    然后您将使用以下命令添加到此集合中:

    set.add(eq.wrap(x));
    

    其中eq 是您对Equivalence 的实现。

    【讨论】:

    • 伟大的 cmets 和许多值得考虑的事情。追问:为什么(可变)集合ArrayList&lt;T&gt;实现equalshashCode?我猜所有(可变的)JDK 集合都是这样做的。
    • 嗯,在某些时候,你必须信任用户;因此,集合 API(包括 Map,即使它本身不是集合​​)定义了 .equals().hashCode(),依赖于元素的 .equals().hashCode()。 JDK 中的某些类可以安全使用,例如,作为 Map 中的键,因为它们是最终的;对于用户定义的类,用户必须承担责任。
    【解决方案2】:

    最好的做法是让可变对象不相等,除非它们是同一个对象。这是因为对象可能会在以后更改。考虑以下

    Set<ProcessBuilder> pbSet = new HashSet<>();
    pbSet.add(x);
    pbSet.add(y);
    // if x and y were equal pbSet would have one element.
    y.setSomething()
    // should pbSet have one or two elements.
    

    比这更糟糕的是相反的情况,两个对象可能不同,但后来却相同。这意味着 Set 会有一个重复的对象。

    有趣的是集合是可变的但仍然有equals和hashCode。我认为出现这种情况的原因是没有不可变的集合。例如字符串覆盖equals(),StringBuilder没有。

    【讨论】:

    • 即使有不可变的集合,也不会改变这样一个事实,如果这个集合的元素是可变的,那么无论如何你都注定要失败......但至少,你有 一些保证健全的 equals/hashCode 实现。我刚刚修复了我的一个宠物项目中的一个错误:请参阅here
    • @Peter:这是一段迷人的 sn-p 代码。我从来没有考虑过这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 2020-04-11
    • 1970-01-01
    • 2011-02-27
    相关资源
    最近更新 更多