12

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 実装におけるこの根本的な問題について認識と行動を起こすには、どのような手段が必要ですか?

4

2 に答える 2

4

バグ 7054089 の例ではなく、ここで示した例を使用して、Java 1.7.0_17 に対するバグを再送信します。StackOverflow の例もそのバージョンで保持されていることを確認しました。Oracle はセキュリティの問題を除いて Java 6 のバグ修正を終了したと聞きました。

元のバグの送信では、指定した URI は不透明な URI であり、評価者を混乱させた可能性があります。RFC 2396 のことだと思います。

また、新しい評価者を得るかもしれません:)

ここで hashCode() の契約を確実に破ったように思えます。

そして、Java 用の StackOverflow のようなコメント メカニズム (または、以前のような基本的なコメント) がないのは残念です。

于 2013-04-29T05:54:14.663 に答える
2

朗報です!Oracle はJDK-7171415で Java 8 のこのバグを修正したようです! 上記のテストが Windows 10 Pro 64 ビットの Java 1.8.0_92 で合格することを確認しました。新しいバグ チケットは以前のバグ チケットのいずれも参照していないため、どのように発生したかはわかりません。しかし、彼らが最終的にそれを修正したことをうれしく思います。

于 2016-09-14T15:24:55.593 に答える