Java Magic. Part 1: java.net.URL

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

英文原文

转载请写明:原文地址

系列文章:

-Java Magic. Part 1: java.net.URL

-Java Magic. Part 2: 0xCAFEBABE

-Java Magic. Part 3: Finally

-Java Magic. Part 4: sun.misc.Unsafe

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

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值的时候。虽然只是个玩笑,但是确实很有帮助

    Java Magic. Part 1: java.net.URL的更多相关文章

    1. Magic Cast Method in Java Magic Trick In Java

      https://www.atlassian.com/blog/archives/magic_trick_in_java https://www.gamlor.info/wordpress/2010/1 ...

    2. Java Magic. Part 4: sun.misc.Unsafe

      Java Magic. Part 4: sun.misc.Unsafe @(Base)[JDK, Unsafe, magic, 黑魔法] 转载请写明:原文地址 系列文章: -Java Magic. P ...

    3. Java Magic. Part 3: Finally

      Java Magic. Part 3: Finally @(Base)[JDK, magic, 黑魔法] 转载请写明:原文地址 英文原文 系列文章: -Java Magic. Part 1: java ...

    4. Java Magic. Part 2: 0xCAFEBABE

      Java Magic. Part 2: 0xCAFEBABE @(Base)[JDK, magic, 黑魔法] 转载请写明:原文地址 英文原文 系列文章: -Java Magic. Part 1: j ...

    5. Java魔法堂:URI、URL(含URL Protocol Handler)和URN

      一.前言 过去一直搞不清什么是URI什么是URL,现在是时候好好弄清楚它们了!本文作为学习笔记,以便日后查询,若有纰漏请大家指正! 二.从URI说起    1. 概念 URI(Uniform Reso ...

    6. java.net.MalformedURLException: Illegal character in URL

      在进行接口测试时,意外发现返回结果报java.net.MalformedURLException: Illegal character in URL,意思是“在URL中的非法字符”,我的参数是经过ba ...

    7. java基础:网络编程TCP,URL

      获取域名的两种方法: package com.lanqiao.java.test; import java.net.InetAddress;import java.net.UnknownHostExc ...

    8. Preferred Java way to ping a HTTP Url for availability

      I need a monitor class that regularly checks whether a given HTTP URL is available. I can take care ...

    9. URL中增加BASE64加密的字符串引起的问题(java.net.MalformedURLException:Illegal character in URL)

      序 昨天在做一个 Demo 的时候,因为是调用第三方的接口,採用的是 HTTP 的通信协议,依照文档上的说明,须要把參数进行加密后增加到 URL 中.可是,就是这个看似普普通通的操作,却让我着实费了非 ...

    随机推荐

    1. php实现Facebook风格的 time ago函数

      php实现Facebook风格的 time ago函数 非常好用,只要把里面的英文替换成中文就行了 英文函数代码如下: <?php function nicetime($date) { if(e ...

    2. phper必知必会(二)

      1.说说你对进程,线程以及协程的理解 进程:是系统进行资源分配和调度的基本单位,是基本操作系统结构的基础.进程是程序基本执行的实体.进程与进程之间是独立的,拥有完全独立的地址空间,进程的切换只发生在内 ...

    3. 【python】python GUI开发框架介绍

      Python GUI开发的库不少.最常用的的也就几个. Tkinter -Tk是Python自带的GUI库, 上手简单, 做个简单界面基本够用了,但是不够美观,功能不全面. wxPython -开源免 ...

    4. ToString yyyy-MM-dd ,MM 小写的故事。

      ToString MM 小写,有可能时间转为 :2013-49-02,放到数据库中查询,就报错.

    5. C++ 常用函数方法

      /* * 拆分字符串 * 参数: * strData 字符串 * split 分隔符 * 返回: * 返回动态数组std::vector<std::string> ,记得要delete 内 ...

    6. 2018 icpc 徐州网络赛 F Features Track

      这个题,我也没想过我这样直接就过了 #include<bits/stdc++.h> using namespace std; ; typedef pair<int,int> p ...

    7. 关于buffer,cache,wb,wt,clean,inv,flush,以及其他

      1. 有时候需要区分buffer和cache:buffer解决CPU写的问题,比如将多次写操作buffer起来一次性更新:cache解决CPU读的问题,将数据cache起来在下次读的时候快速取用. 2 ...

    8. NoSQL非结构化数据库高级培训课程-大纲

      一.课程概述 本课程面向No-SQL开发人员.系统分析和系统架构师,目的在于帮助他们建立起完整的No-SQL数据库的概念,应用场景.相关开源技术框架和优缺点. 二.课程大纲 主题 时间 主题 No-S ...

    9. Redis高速内存缓冲平台可视化监控之RedisLive配置实战

      一.引用 这两天在弄Reids高速缓存平台的图形化监控,由于对于Python并不是很熟悉,安装过程中遇到了不少问题,包括: 1.python必备安装包的安装问题 2.Redis Live界面显示问题 ...

    10. bzoj2048 书堆

      Description Input 第一行正整数 N M Output 一行(有换行符),L,表示水平延伸最远的整数距离 (不大于答案的最大整数) 贪心地把最高的书尽量向右放可以得到最优解,因而最高的 ...