Основная часть контракта Java Object
заключается в том, что метод hashCode()
должен соответствовать методу equals()
. Это имеет смысл и легко понять: если два объекта "равны" каким-то образом, они должны возвращать один и тот же хэш-код. Если нет, вы можете, например, поставить один объект в HashSet
, а затем проверить, будет ли отдельный экземпляр установлен в наборе и некорректно вернуться false
, хотя метод equals()
рассмотрел бы эквивалент объектов.
На самом деле код URI Java имеет эту проблему с 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()));
}
}
Управляющие последовательности URI, как в RFC 3968, нечувствительны к регистру; т.е. %2A
и %2A
считаются эквивалентными. Реализация Java URI.equals()
учитывает это. Однако реализация URI.hashCode()
не учитывает это! Это означает, что два экземпляра URI, которые возвращают true
для URI.equals()
, тем не менее могут возвращать разные хэш-коды, как показано в приведенном выше коде!
Я представил эту проблему, которая предположительно приводит к ошибке Java 7134993, но эта ошибка больше не доступна. Тем не менее, эта же проблема показана в Java Ошибка 7054089. (Я не уверен, что это было из моего представления или от кого-то другого, но проблема такая же.) Однако ошибка была отклонена при оценке, . Приведенные примеры - непрозрачные URI, и поэтому конкретная схема детали не анализируются ".
Тот, кто оценил эту ошибку, должен быть не знаком с тем, что означает, что для equals()
и hashCode()
должно быть последовательным. В контракте для Object.equals()
четко сказано: "Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат". Обратите внимание на использование "must", а не "should".
Дело в том, что, хотя оценщик утверждает, что URI является "непрозрачным" и "не анализируется", реализация URI.equals()
(вопреки его/ее утверждениям) действительно анализирует URI и делает скидку на случай нечувствительность. Реализация URI.hashCode()
отсутствует.
Итак, я здесь совершенно плотный и пропуская что-то очевидное? Если я, кто-то, пожалуйста, просветите меня о моей ошибке, и я помету ваш ответ как правильный. В противном случае возникает вопрос: теперь, когда Sun/Oracle больше не допускает комментариев к поданным ошибкам, каким образом я должен получить признание и действия по этой фундаментальной проблеме в реализации Java первичного идентификатора Интернета, URI?