2017-10-13 101 views
0

Java中是否有任何內置合同檢查對於hashcode和equals函數之間的契約?Java合同檢查 - 內置?例如。哈希碼/等於

對於這個問題,讓我們堅持以hashcode/equals合同爲例,但我一般感興趣的是合同檢查。我曾在多個地方讀取equals和hashCode必須滿足Java中的「合同」:

  • 的Equals必須遵循的equivalence relation的三個規則,也必須是在重複調用一致
  • 相等對象意味着等於哈希碼

我瞭解條件,而且他們對我有意義。但是,我想知道,這僅僅是一個寫在紙上的合同 - 本質上是開發人員不寫出錯誤代碼的強有力的指導原則 - 或者它會被Java作爲編譯時或運行時異常捕獲的東西?

+1

它不會被Java作爲編譯時或運行時異常捕獲。 (編寫代碼)堅持繼續RACT。 – nbokmans

+0

如果等於相同並不意味着哈希碼相同,那麼你可以得到一些奇怪的行爲。例如。相同的對象可以映射到散列映射中的不同桶。 –

+0

謝謝你們,那就是我的想法。所以對於Java而言,它基本上是一個強有力的指導方針,不會編寫那些將會非常糟糕和錯誤的代碼......但是我們仍然可以在理論上編寫一個違反合同的程序,並且它可以編譯並運行良好,多年來沒有任何錯誤變得明顯。 –

回答

1

它不會在編譯時執行。

某些類可能會在運行時強制執行 - 例如,您可以編寫一個方法來檢查兩個相等的對象是否具有相同的哈希碼或發送異常。

另請注意,有些情況下您可能想故意偏離推薦的合同。

+0

謝謝。我真的很想看到一個例子,在這個例子中,這個合同實際上是可取的嗎? –

+0

例如'Comparable'「強烈建議」compareTo'與'equals'(即'(a.compareTo(b)== 0)==(a.equals(b)')一致。偏離這個建議是有用的,例如:https://stackoverflow.com/a/14534751/829571 – assylias

1

這是不是(不能夠)自動夾在編譯或運行時(除非你明確地檢查它

簡單的反例:

public boolean equals(Object other){ 
    return new Random().nextInt(3) == new Random().nextInt(3); 
} 

public int hashCode() { 
    return new Random().nextInt(3); 
} 

然而,它是一個好主意,創建單元測試來檢查這些合同我遇到了由於使用嚴重實現的equals/hashcode而難以發現的錯誤

+0

是的,我越想越多,我越發覺這不能被自動捕獲。我想知道是否有任何框架試圖在編譯時檢查這個違反合同的情況,這將是一個有趣的項目 –

+1

如果你對這方面的某些東西感興趣,請查看https: //en.wikipedia.org/wiki/Java_Modeling_Language –

+0

不錯!非常有趣,它看起來像允許你至少用一種自然的方式指定這些聯繫人,像Hoare triples這樣的方式,然後將其轉換爲運行時斷言。我懷疑是否有可能編寫一個通用的工具,它可以在編譯時爲任何JML規範提供YES/NO答案 - 可能是像計算機科學中大多數這些常規事物一樣的不可判定的問題。無論如何,非常有趣。願望行業更多地使用這一點。 –