我最近发现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()
的覆盖。
我觉得有一个更深层次的原因,超越这一课。也许这是故意的?
答案 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
的实现。