为什么类ProcessBuilder不重写equals()?

时间:2013-07-07 16:12:17

标签: java jdk6

我最近发现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()的覆盖。

我觉得有一个更深层次的原因,超越这一课。也许这是故意的?

2 个答案:

答案 0 :(得分:1)

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

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没有。

答案 1 :(得分:1)

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

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

有关此Equivalence的更多信息:对于本质上可变的“不稳定”类X,但您可以保证在给定上下文中保持等效,则实现Equivalence<X>。然后你将X的这些实例“包装”成例如:

Set<Equivalence.Wrapper<X>>

然后您将使用以下内容添加到此集:

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

其中eq是您Equivalence的实现。