0

我最近发现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
}

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

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

4

2 回答 2

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。我认为出现这种情况的原因是没有不可变的集合。例如 String 覆盖 equals(),StringBuilder 没有。

于 2013-07-07T16:17:17.387 回答
1

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

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

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

Set<Equivalence.Wrapper<X>>

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

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

你在哪里eq实现Equivalence.

于 2013-07-07T16:39:05.193 回答