JavaObject
コントラクトの基本的な部分は、hashCode()
メソッドがメソッドと一貫していなければならないということequals()
です。これは理にかなっており、簡単に理解できます。2 つのオブジェクトが何らかの形で「等しい」場合、それらは同じハッシュ コードを返す必要があります。そうでない場合は、たとえば、1 つのオブジェクトを に配置しHashSet
、後で別のインスタンスがセットに含まれているかどうかを確認し、メソッドがオブジェクトを同等と見なしたfalse
としても、誤って を返すことができます。equals()
実際、Java の URI コードには、Java 6 の時点でこの問題があります。次のコードを試してください。
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.net.URI;
import org.junit.Test;
public class URITest
{
@Test
public void testURIHashCode()
{
final URI uri1 = URI.create("http://www.example.com/foo%2Abar");
final URI uri2 = URI.create("http://www.example.com/foo%2abar");
assertThat("URIs are not equal.", uri1, equalTo(uri2));
assertThat("Equal URIs do not have same hash code.", uri1.hashCode(), equalTo(uri2.hashCode()));
}
}
RFC 3968 に従って、URI エスケープ シーケンスは大文字と小文字を区別しません。つまり、同等%2A
と%2a
見なされます。JavaURI.equals()
実装はこれを考慮に入れています。ただし、URI.hashCode()
実装ではこれが考慮されていません。これは、上記のコードに示されているように、それにもかかわらず返される 2 つの URI インスタンスが異なるハッシュ コードを返す可能性がtrue
あることを意味します。URI.equals()
この問題を提出した結果、Java Bug 7134993 が発生したと思われますが、そのバグは利用できなくなりました。ただし、同じ問題が Java Bug 7054089に示されています。(これが私の提出物によるものなのか、他の誰かによるものなのかはわかりませんが、問題は同じです。)しかし、バグは評価で否定されました。解析しました。」
このバグを評価した人は誰でも、それが何を意味しequals()
、hashCode()
一貫性があるかについてよく知らなかったに違いありません。のコントラクトObject.equals()
には、「equals(Object) メソッドに従って 2 つのオブジェクトが等しい場合、2 つのオブジェクトのそれぞれで hashCode メソッドを呼び出すと、同じ整数結果が生成される必要がある」と明確に記載されています。「すべき」ではなく「しなければならない」の使用に注意してください。
ここでのポイントは、評価者が URI は「不透明」で「解析されていない」と主張しているにもかかわらず、URI.equals()
実装は (彼/彼女の主張に反して) 実際に URI を解析し、大文字と小文字を区別しないことを考慮しているということです。URI.hashCode()
実装はそうではありません。
それで、私はここで完全に密集していて、明らかな何かを見逃していますか? もしそうなら、誰かが私の間違いについて教えてください。あなたの答えを正しいものとしてマークします。それ以外の場合、問題は次のとおりです。Sun/Oracle は報告されたバグに対するコメントを許可しなくなったようですが、インターネットの主要な識別子である URI の Java 実装におけるこの根本的な問題について認識と行動を起こすには、どのような手段が必要ですか?