博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java Magic. Part 1: java.net.URL
阅读量:7075 次
发布时间:2019-06-28

本文共 1544 字,大约阅读时间需要 5 分钟。

Java Magic. Part 1: java.net.URL

@(Base)[JDK, url, magic, 黑魔法]

转载请写明:

系列文章:

-

-
-
-

废话不多说,首先我们看如下代码:

HashSet set = new HashSet();set.add(new URL("http://google.com"));set.contains(new URL("http://google.com"));Thread.sleep(60000);set.contains(new URL("http://google.com"));

代码的第3行和第5行分别会输出什么呢?

当然不会是true, 如果是true的话,这篇文章也就不会有java黑魔法的后缀了。简单地说吧,当你有运行的PC有网络链接的时候,返回结果是false。如果你关掉你的网络链接,比如wi-if,那么该段程序的返回值就是true

这么奇葩的直接原因就是URL类的hashCode()equals()方法的实现。

下面是hashCode()方法:

public synchronized int hashCode() {  if (hashCode != -1)    return hashCode;  hashCode = handler.hashCode(this);  return hashCode;}

值得注意的是,URL是一个immutable的对象。

我们可以显然看到这个URL的hashCode值是一个私有域。也就是说,只会计算一次。什么是代码中提到的handler呢?它其实是URLStreamHandler的子类,具体的类型和当前的网络协议类型(file,http,ftp)有着密不可分的关系。我们可以看看URL.hashCode()方法上面的注释:

The hash code is based upon all the URL components relevant for URL comparison. As such, this operation is a blocking operation.

翻译过来就是:hash code的计算和URL的所有相关属性都有关系。例如,这个操作是不是blocking的。

WTF,BLOCKING OPERATION?!

好了这个事情我们暂时放一边。另外这个hashCode的计算奇葩的地方在于,这个handler竟然会解析ip地址参与计算。我们拿这个google.com为例子。当host的ip是动态的时候,或者说有一个域名解析的负载均衡的时候,这个hashCode()方法就会针对google.com计算出两个完全不同的hashCode值。

其实最让人无法接受的是URLStreamHandler会开启一个URLConnection,当然这又是另外一个话题啦。

How to avoid this?

  • java.net.URI来替换java.net.URL。虽然这不算是个非常好的办法,但至少有一个靠谱hashCode。
  • 千万不要在collections中使用java.net.URL。一个好的选择是,在collections中放string对象来表示hostname,然后当需要的时候再使用URL对象。
  • 关闭你的网络连接,当计算的hashCode值的时候。虽然只是个玩笑,但是确实很有帮助 :)
  • 自行替换URLStreamHandler

我非常确认java.net.URL有非常多有用的应用场景。但是至少不是像上面那么用啦~

转载于:https://www.cnblogs.com/maxmys/p/5183601.html

你可能感兴趣的文章