为什么java.net.URL的hashcode将主机解析为IP?

在第一个决议之后它的想法是否依赖于操作系统缓存? 这似乎效率低下,并且在多个域解析为相同IP的情况下,这是不正确的。 我错过了什么?

很多人认为这是一个非常糟糕的主意。

这是来自URI的Javadoc的一些解释。 这个问题也很有用。

为什么java.net.URL的hashcode将主机解析为IP?

有两个原因。 首先是:

  • URL类的行为旨在模拟URL作为网络可访问资源的定位器。 具体来说, equalshashCode()的设计使得两个URL实例在它们找到相同资源时是相等的。 这要求将DNS名称解析为IP地址。

事后看来,我们知道以下内容:

  1. URL.equals方法不能可靠地确定两个URL字符串是否是同一资源的定位符。 原因包括虚拟主机,HTTP 30x转发和URL的服务器内部映射等。

  2. URL.equalsURL.hashcode的IP解析行为是没有经验的Java程序员的陷阱,尽管它已被清楚地记录下来。

  3. 即使在导致正确答案的情况下, URL.equals IP解析也可能是意外(和不需要的)性能URL.equals

简而言之…… URL的设计方面是错误的。

这带来了第二个更重要的原因。

  • URL.equals(Object)的行为是在很久以前定义的,如果不破坏(可能)数百万个已部署的Java应用程序,现在就无法进行更改。 这排除了Sun(现在的Oracle)将改变它的任何可能性。

也许Java类库的(假设的)inheritance者的设计者可以解决这个问题(以及其他问题)。 当然,为了实现这一点,必须抛弃与现有Java程序的向后兼容性。

最后,Java应用程序开发人员的真正答案是简单地使用URI类。 (真正的软件工程就是尽可能地完成工作,而不是抱怨你提供的工具。)


1 – 当我说“不能”时,我的意思是理论上不可能。 处理一些更困难的情况需要更改HTTP协议。 即使假设的HTTP 2.0“修复”了这个问题,我们仍然会在20年内处理遗留的HTTP 1.1服务器……因此URL.equals仍会被破坏。

不要使用java.net.URL 。 这是你问题的简单答案。 请改用java.net.URI ,它不会执行主机名解析。

hashCode()equals()密切相关。 有关此行为的说明在equals()的文档中描述如下:

如果两个主机名都可以解析为相同的IP地址,则认为两个主机是等效的。 否则,如果无法解析任何一个主机名,则主机名必须相等而不考虑大小写; 或两个主机名都等于​​null。

来源: java.net.URL.equals() docs。