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

17

第一次解析后,这个想法会依赖于操作系统缓存吗?但这似乎效率低下,在多个域名解析到同一个IP的情况下,可能不正确。我错过了什么吗?

3个回答

36
为什么java.net.URL的哈希码会将主机名解析为IP地址?
有两个原因。第一个是:
URL类的行为被设计为模拟URL作为可访问网络资源的定位器,特别是如果两个URL实例定位到相同的资源,则equals()和hashCode()方法被设计为相等。这要求DNS名称必须被解析成IP地址。
从 hindsight 的角度来看,我们知道以下内容:
1. URL.equals() 方法不能可靠地确定两个URL字符串是否为同一资源的定位器。原因包括虚拟托管、HTTP 30x 转发、服务器内部对URL的映射等。 2. URL.equals() 和 URL.hashcode() 的 IP 解析行为是 Java 初学者的陷阱,尽管已经有明确的文档说明。 3. 即使在导致正确答案的情况下,URL.equals() 中的 IP 解析也可能是意外(和不必要)的性能开销。
简而言之...URL的设计方面是一个错误。
这引出了第二个更重要的原因。
URL.equals(Object) 的行为早在很久以前就被定义了,现在改变它将不可能不破坏(可能)数百万部署的Java应用程序。这排除了Sun(现在的Oracle)将其更改的任何可能性。
也许(假设存在)Java类库的继任者的设计者可以修复这个问题(和其他问题)。当然,要实现这一点,必须放弃对现有Java程序的向后兼容性。

最后,对于Java应用程序开发人员的真正答案是直接使用URI类。(真正的软件工程既要尽力完成工作,也不要抱怨提供给你的工具。)


1 - 当我在上面说"不能"时,我的意思是理论上不可能。处理一些更困难的情况需要改变HTTP协议。即使某个(假想的)未来版本的HTTP“修复”了这个问题,我们仍然会在20年后处理遗留的HTTP服务器......因此URL.equals仍然会出现问题。


1
现在要想改变它,可能会导致数百万已部署的Java应用程序崩溃,因此这是不可能的。 -- 可以说,依赖于这种行为的应用程序已经出现了故障。 - Dolda2000
@Dolda2000 - 也许吧。但即使如此,在我看来,Oracle也不可能冒着为一部分客户“修复”URI类而使情况变得更糟的风险。对于Oracle来说,这是适得其反的。(对于现有应用程序没有问题的付费客户,受益为零。它只会帮助编写新应用程序的人,而对Oracle的好处是最小的。) - Stephen C
(显然,我指的是“修复URL类”。URI类并未损坏。) - Stephen C

9

很多人认为这是一个非常糟糕的想法。

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


6
hashCode()equals()密切相关。关于这种行为的解释在equals()文档中描述如下:
如果两个主机名都可以解析成相同的IP地址,则认为它们等效;否则,如果任何一个主机名无法解析,则主机名必须相等,而不考虑大小写;或者两个主机名都等于null。
来源:java.net.URL.equals()文档。

虽然我认为使用URL是错误的,即使它的设计是出于良好的意图,但我还是要赞成解释为什么URL会以这种方式运作。 - C. K. Young
2
就本问题而言,争论使用URL/URI会偏离主题。 - Dolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接