Как получить распознавание ошибки URI hashCode() URI, которая была ненадлежащим образом отказана
Основная часть контракта 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?
Ответы
Ответ 1
Хорошие новости! Oracle, похоже, исправил эту ошибку для Java 8 в JDK-7171415! Я подтвердил, что мой тест выше теперь проходит в Java 1.8.0_92 на Windows 10 Pro 64-бит. Новый биг-код не ссылается ни на один из предыдущих, поэтому я не знаю, как это произошло. Но я рад, что они, наконец, исправили это.
Ответ 2
Я бы повторно представил ошибку против Java 1.7.0_17, используя приведенный здесь пример, а не тот, который указан в ошибке 7054089. Я проверил, что ваш пример StackOverflow также содержится в этой версии. Я слышал, что Oracle закрыла исправление ошибок на Java 6, за исключением проблем безопасности.
В исходной отправке ошибок URI, которые вы указали, являются непрозрачными URI, и это, возможно, отключило оценщика. И я думаю, вы имеете в виду RFC 2396.
Кроме того, вы можете получить новый оценщик:)
Мне кажется, что они определенно нарушили контракт для hashCode() здесь.
И стыдно, что у них нет механизма StackOverflow, такого как комментарий для Java (или основных комментариев, как в прошлом).