2013-07-07 40 views
0

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

我很惊讶地看到这个代码不工作:

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()

我有一种感觉,有一个更深的原因,超越了这一类。也许这是故意的?

回答

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不会。

+0

即使有不可改变的集合,它不会改变,如果这个集合的元素是可变的,你是无论如何注定的事实......但至少,你有一个理智的_some_保证等于/的hashCode实现。我刚才固定我的一个宠物项目中的错误:参见[这里](https://github.com/fge/abic/commit/43102fbc46da0f6042452541f4a3b9cdcd60cbaa) – fge

+0

@Peter:这是一个代码迷人片段。我从未考虑过这种情况。 – kevinarpe

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的实现。

+0

伟大的评论和很多考虑。后续:为什么(可变)集合'ArrayList '实现'equals'和'hashCode'?我猜测所有(可变的)JDK集合都是一样的。 – kevinarpe

+0

那么,在某些时候,你必须相信用户;这样,集合API(包括'Map'即使它不是集合本身)限定'.equals()'和'.hashCode()',依托元素'.equals()'和'。的hashCode()'。在JDK有些类使用是安全的,例如,作为键在'Map'因为他们是最终的;对于用户定义的类,用户必须承担责任。 – fge

相关问题