Java谜题选-II

题目2:关于Sets的更多Fun。

对了,这个题目表面上看也是关于Sets的…

程序

import java.net.*;public class UrlSet {  private static final String[] URL_NAMES = {    "http://javapuzzlers.com",    "http://apache2-snort.skybar.dreamhost.com",    "http://www.google.com",    "http://javapuzzlers.com",    "http://findbugs.sourceforge.net",    "http://www.bianceng.cn"   };  public static void main (string[] args)            throws MalformedURLException {      Set favorites = new HashSet();      for (String urlName : URL_NAMES)          favorites.add(new URL(urlName));      System.out.println(favorites.size());  }}

答案

(a) 4

(b) 5

(c) 6

(d) None of the above

译者序:

因为最近忙,这个第二集的答案出得太晚了点,希望大家见谅。

另:程序中的一行忘记了括号,Set favorites = new HashSet(); 我已经加上了,多谢读者的细心。

谜题一之答案,分析过程,以及经验教训

答案

(d) None of the above

分析过程

如果运行此程序所在的机器与互联网相接,那么答案将是(a) 4。为什么呢?因为URL接口的equals和hashCode方法彻底搞错了。

“http://javapuzzlers.com”和”http://apache2-snort.skybar.dreamhost.com”,这两个完全不同的网址,解析成的IP地址竟是完全相同的!(译者注:寄存这两个不同网址的web服务器显然只有一个,用的是以名称为基础的共享IP网络寄存技术,这显然是出题者有意为之,即所谓的Virtual Host)

根据URL类的技术文档,两个URL对象将被认为相等,如果以下条件得到满足:

使用同样的通信协议,引用相当的寄存服务器,使用同样的端口,同样的文件或同样的一部分文件。

两个寄存服务器被认为是相等的,如果两个名称被解析成同一个IP地址,或者两个名称都不可被解析,或者两个名称同为空(null)。

因此,如果运行此程序所在的机器不与互联网相接,得到的结果将是1,应为所有名称都不可被解析。这个题的答案因此是(d) None of the above。不同网络环境下的运行,就有不同的结果,这实在是比较糟糕的。

URL类的equals方法是不支持Virtual Host(虚拟寄存)功能的。93年URL类被加进java平台时,基本是没有虚拟寄存这个技术的。

经验教训

URL类有bug,不要使用URL,应该使用URI类。

URI类的equals方法只会进行字符的比较。程序改成Set favorites = new HashSet(); 打印出来的结果就是5了,因为有两个”http://javapuzzlers.com”的缘故。

同时,favorites.add(new URL(urlName))这行程序也要改成favorites.add(URI.create(uriname));

注意这里用的是更好的静态工厂的模式,而不是一般的创建,这也是URI所不同于URL的。

我躺下来,以一张报纸当枕头。高高在我上方的,

Java谜题选-II

相关文章:

你感兴趣的文章:

标签云: