今天看到个有趣的代码,被这套操作震惊😱了一下午.
请听题
把java.net.URL对象,进行equals比较,会发生什么?
题目
URL url = new URL("http://afk.now.sh");
URL url3 = new URL("http://carbon.now.sh");
System.out.println(url.equals(url3));
答案(白色的)
DNS 查询, 他会加锁解析DNS,然后比较指向的ip是否一致.
true
😱
这玩意直接把我看懵了.
然后,就去看了URL
的equals
方法实现.
然后,我就更懵😳了.
URL.equals
public boolean equals(Object obj) {
if (!(obj instanceof URL u2))
return false;
return handler.equals(this, u2);
}
源码是这样, 他借助了一个URLStreamHandler
的sameFile
方法来判断逻辑的.
sameFile
protected boolean sameFile(URL u1, URL u2) {
// Compare the protocols.
if (!((u1.getProtocol() == u2.getProtocol()) ||
(u1.getProtocol() != null &&
u1.getProtocol().equalsIgnoreCase(u2.getProtocol()))))
return false;
// Compare the files.
if (!(u1.getFile() == u2.getFile() ||
(u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
return false;
// Compare the ports.
int port1, port2;
port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort();
port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort();
if (port1 != port2)
return false;
// Compare the hosts.
if (!hostsEqual(u1, u2))
return false;
return true;
}
很长, 不过整体是分4步:
-
比较协议 -
比较文件 -
比较port -
比较host
hostsEqual
最后一步这个hostEqual
就是真的让人跌掉下巴了.代码是这样的.
protected boolean hostsEqual(URL u1, URL u2) {
InetAddress a1 = getHostAddress(u1);
InetAddress a2 = getHostAddress(u2);
// if we have internet address for both, compare them
if (a1 != null && a2 != null) {
return a1.equals(a2);
// else, if both have host names, compare them
} else if (u1.getHost() != null && u2.getHost() != null)
return u1.getHost().equalsIgnoreCase(u2.getHost());
else
return u1.getHost() == null && u2.getHost() == null;
}
关键点在开头的getHostAddress
上
synchronized InetAddress getHostAddress() {
if (hostAddress != null) {
return hostAddress;
}
if (host == null || host.isEmpty()) {
return null;
}
try {
hostAddress = InetAddress.getByName(host);
} catch (UnknownHostException | SecurityException ex) {
return null;
}
return hostAddress;
}
他会调用两次DNS
解析, 检查一下,获取ip地址….. 而且这方法还是带锁的…
神奇的上古代码
代码Java1.3里出现的, 也就是1999年,23多年前的代码了. 要是个男孩子都够结婚年龄,是个女孩子都已经是2个孩子的妈了.
这是给当年的情景准备的,现代互联网,多个域名指向同一个ip的场景很常见, 这个写法基本上算是一点用都没有.
然而,为了兼容性还留着.😯
经验&教训
用URL
的equals
方法的人确实不多, 不是什么常规操作.
不过万一某一天, 谁手贱把这东西给用到HashMap
或者HashSet
之类的地方,再或者给了stream
操作…那就等坑吧.
项目里如果有什么静态扫描工具的话, 该用上就用上,可以以防万一.
除了这个坑爹的URL.equals
,还有Stack
,HashTable
,这一类的上古集合类,发现用就直接报警.早发现早治疗.
当然, 还有一个一定要记得的事,千万不要不看文档瞎写.很多类, 平时用的很多,但是如果没看过文档, 他们的某些方法,就是最熟悉的陌生人,坑死人不偿命.
五一劳动节就要到了, 祝大家五一节快乐,高速免费🆓快乐.
原文始发于微信公众号(K字的研究):千万别用URL.equals【痛苦面具.gif】
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/24762.html