2013-07-07 52 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

相關問題