java - 如何识别已被不当拒绝的 Java URI hashCode() 错误

标签 java uri equals hashcode

Java Object 契约的一个基本部分是 hashCode() 方法应该与 equals() 方法一致。这是有道理的,也很容易理解:如果两个对象在某种程度上“相等”,它们应该返回相同的哈希码。如果不是,您可以将一个对象放入 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 被认为是等价的。 Java URI.equals() 实现考虑了这一点。但是,URI.hashCode() 实现没有考虑到这一点!这意味着为 URI.equals() 返回 true 的两个 URI 实例仍然可以返回不同的哈希码,如上面的代码所示!

我提交了这个问题,据推测它会导致 Java 错误 7134993,但该错误不再可用。不过,Java Bug 7054089 中显示了同样的问题。 . (我不确定这是我提交的还是其他人提交的,但问题是一样的。)但是,评估拒绝了该错误,“引用的示例是不透明的 URI,因此方案特定部分未被解析。”

评估此错误的人一定不熟悉 equals()hashCode() 保持一致意味着什么。 Object.equals() 的约定明确指出,“如果根据 equals(Object) 方法两个对象相等,则对这两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果”请注意使用“必须”,而不是“应该”。

这里的要点是,即使评估者声称 URI 是“不透明的”和“未解析的”,URI.equals() 实现(与他/她的说法相反)是实际上是解析 URI 并允许不区分大小写。 URI.hashCode() 实现不是。

所以我是不是在这里完全密集而遗漏了一些明显的东西?如果是,请有人告诉我我的错误,我会将您的回答标记为正确。否则,问题是:既然 Sun/Oracle 似乎不再允许对已提交的错误发表评论,那么在 Internet 的主要标识符 URI 的 Java 实现中,我有什么办法来获得对这个基本问题的认可和采取行动?

最佳答案

我会使用您在此处提供的示例而不是错误 7054089 中的示例重新提交针对 Java 1.7.0_17 的错误。我检查过您的 StackOverflow 示例也适用于该版本。我听说 Oracle 已经关闭了 Java 6 上除安全问题之外的错误修复。

在您提交的原始错误中,您提供的 URI 是不透明的 URI,这可能会让评估者失望。我认为你的意思是 RFC 2396。

此外,您可能会得到一个新的评估者:)

在我看来,他们在这里肯定违反了 hashCode() 的约定。

很遗憾他们没有像 StackOverflow 这样的 Java 注释机制(或者像过去那样的基本注释。)

关于java - 如何识别已被不当拒绝的 Java URI hashCode() 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16257996/

相关文章:

android - 从 Android NFC Intent 获取 URI

c# - GetHashCode问题

javascript - 比较两个对象数组 JS

java - 如何在 Android 应用程序中持久保存一个对象?

Android GCM PushNotification - 在应用程序中添加自定义声音文件

java - 无法访问内部类中的变量而不将其设为 Final

c# - 为什么我的流不可读?

java - 字符串匹配的效率,Equals 与 Matches 方法

java - AES-256 加密 : Generate 256bits(32bytes) key from my fixed string

java - 解析 DecimalFormat 以避免科学计数法