阅读更多

3顶
2踩

编程语言
原文来自:DZone
译文来自:后端技术杂谈

StackOverflow(后边简称so)发展到目前,已经成为了全球开发者的金矿。它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西。这篇文章是在我们审阅了so上最流行的Java问题以及答案后从中挑出来的。即使你是一个有丰富经验的开发者,也能从中学到不少东西。

分支预测

SO上最多投票的一个Java问题是:为什么处理一个排序数组要比非排序数组快的多。为了回答这个问题,你需要使用分支预测(branch prediction)。分支预测是一种架构,旨在通过在真实的路径发生前猜测某一分支的下一步来提升处理过程。

分支在这里即一个if语句。这样的话,如果是一个排序数组,那么分支预测将会进行,否则不会进行。Mysticial(so上的一个回答者)试图使用铁路和火车来简单介绍这个概念。假设你在铁轨连接处要决定火车要走哪条路,你会选择左边还是右边?你可以拦住火车,然后问司机该往那里,但是这样会让整个过程变慢。因此你只能去猜正确的方向,那么如何去猜呢?最好的办法就是通过观察目前这个火车每次经过时的路线,推测出正确的方向。

这就是分支预测:识别模式并使用它。

不幸的是,这个问题的提问者是分支预测失败的受害者。因为他的分支没有任何可以识别出的模式,所以预测出的行为是随机的。

Java中的安全

另一个流行的Java问题是:为什么在Java中有关密码的地方更加喜欢使用char[]而不是String?其实原始的问题更加具体一些,就是问的在Swing中,password控件有一个getPassword方法(返回char[]而不是getText()返回的String)。

其实这里不用惊讶-这是一个安全问题。String是不可变的,意味着一旦它被创建了,那么你就不可能去修改它。这也意味着在GC之前,你对这些数据不能做任何处理。因此,只要有人能够访问你的内存,那么String就有可能被他获取到。

这也就是为什么要使用char数组。你可以显示地清除数据或者覆盖它。这样密码这种敏感数据即使GC还没有进行也不会再在系统留下痕迹。

异常

即使很多开发者倾向于忽略对受检异常的处理,SO上仍然有很多关于异常的问题。其中一个最流行的问题是:什么是NullPointerException,我该怎么处理它?对此,我们并没有感到惊讶,因为这个问题也是在生产环境的Java应用中排名第一的异常。

实际上,当NullPointerException(或者其他exception)在系统出现的时候,我们可以发出一个告警。因为这种异常一般情况下都是业务代码逻辑有问题造成(笔者注)。

为什么这段代码使用随机字符串打印出了”hello world”
问题链接:http://stackoverflow.com/questions/15182496/why-does-this-code-using-random-strings-print-hello-world

这个问题给出了下面的代码,并打印出了”hello world”
System.out.println(randomString(-229985452) + " " + randomString(-147909649));

public static String randomString(int i){
    Random ran = new Random(i);
    StringBuilder sb = new StringBuilder();
    while (true)
    {
        int k = ran.nextInt(27);
        if (k == 0)
            break;

        sb.append((char)('`' + k));
    }

    return sb.toString();
}

其实,选择一组随机的整数并不是随机的。给定一个seed参数(在这个例子中是-229985452和-147909649), 那么每次随机,同样的seed则会产生同样的输出。

Random(-229985452).nextInt(27)产生的前六个数字:8, 5, 12, 12, 15, 0

Random(-147909649).nextInt(27)产生的前六个数字:23, 15, 18, 12, 4, 0

这样,最终输出的就是”hello world”。

为什么两个时间戳相减(in 1927)得出一个奇怪的结果?

问题链接:http://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result
public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

按说上面的代码最后的结果应该是1,但实际的输出却是353。其实,这是一个时区的问题。1927年12月31号24:00,上海时间往回调整了5分钟52秒,因此”1927-12-31 23:54:08”发生了两次,Java将后面一次实例化成了本地的这个时间。因此和前一秒的差距成了353。

我们需要指出,如果你试着来运行这段代码,结果并不一定是353。Jon Skeet指出了这一点,在时区数据库项目2014版中,这个改变的时间点改到了1900-12-31,因此成了344秒的差距。

无法被捕获的ChuckNorrisException

问题链接:http://stackoverflow.com/questions/13883166/uncatchable-chucknorrisexception

这里有一个很明显的问题:如果有exception被抛出,但是没有任何办法去catch,那么应用会崩溃吗?或者如这个问题所问:是否可以写一段Java代码让一个假设的java.lang.ChuckNorrisException无法被捕获。

答案是可以,但是这里有一个”但是”。你可以编译一段代码抛出一个ChuckNorrisException,但是在Runtime时动态生成一个并不继承于Throwable接口的ChuckNorrisException类。当然,为了让这个过程可以进行,你需要关闭掉字节码验证。jtahlborn给出了完整的解决办法。

哈希表

哈希表是另外一个在SO上流行的问题系列。许多用户都想要知道所有集合类之间的区别,什么时候该使用哪种集合。

迭代顺序是主要考虑的因素。使用HashMap则忽略了所有的顺序信息,也就是获取元素的顺序和你插入元素的顺序是没有任何关系的;使用TreeMap则会得到一个排序好的迭代集合;使用LinkedHashMap则是一个FIFO的顺序。

如果你还是对这些感到困惑,这里有一个相关说明的图表可以参考(Rebel Labs制作)。



总结

对于Java,其实关键的不在于你懂多少,而是在于你可以一直学到更多的东西。StackOverflow不仅在code上的一些问题可以帮助我们,也有助于我们回过头来去深入地学习一些我们已经知道的知识。
  • 大小: 436.2 KB
3
2
评论 共 3 条 请登录后发表评论
3 楼 lizhuang 2016-08-15 16:31
错别字好多
2 楼 yqbjtu 2016-08-15 15:37
为什么两个时间戳相减(in 1927)得出一个奇怪的结果?

在jdk7上测试结果是1, 我是北京时区
1 楼 Kevin.Y.S 2016-08-15 09:21
这是啥、、、、

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • P2P之UDP穿透NAT的原理与实现源代码

    P2P之UDP穿透NAT的原理与实现附源代码,书我就没有传了,我想对想掌握P2P,NAT技术的朋友还是有一定的帮助吧!~~

  • P2P之UDP穿透NAT的原理与实现资料+源代码

    P2P之UDP穿透NAT的原理与实现资料+源代码,适合初学者的探索与借用!是C语言的哦!

  • P2P之UDP穿透NAT的原理与C#实现(源码和描述)

    P2P之UDP穿透NAT的原理与C#实现(源码和描述)

  • UDP内网穿透讲解及代码实现

    本文转自http://blog.chinaunix.net/u/24606/showart.php?id=425445——》UDP内网穿透讲解及代码实现http://blog.chinaunix.net/u/24606/showart.php?id=425464——》P2P 之 TCP穿透NAT的原理首先先介绍一些基本概念:    NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用。NAT分为两大类

  • HCIP(三)网络类型、HDLC协议、ppp协议

    (一)网络类型 --- 根据数据链路层运行协议及规则划分的 P2P --- Point to Point --- 点到点网络 MA --- Multi-Access Network ---- 多点接入网络 BMA --- Broadcast … --- 广播型多点接入网络 NBMA ---Non-Broadcast ----非广播型多点接入网络 以太网 --- 重要特点 --- 需要在数据中添加MAC地址 原因:利用以太网搭建的二层网络中可以包含多个(两个或两个以上)的接口,每...

  • Java通过socket进行内网穿透简单实现(附源码)

    Java通过socket进行内网穿透简单实现需求背景需求背景1分析需求背景2分析 需求背景 ##背景1,如图,需要实现家里电脑能访问公司的Git代码服务器,实现从家里就能提交git代码的目的。 ##背景2,如图,有内网1和内网2,2个内网里面的2台机器如192.168.56.101,172.168.201.20两台,都不能上网,需要实现能互相通信。 需求背景1分析 对于背景1的需求,属于较常用的内网穿透功能,网上有开源的方案如go语言实现的frp,本次为了学习,通过Java的socket编程,进

  • UDP打洞,内网穿透(附JAVA代码)

    举个例子:在网页上输入www.baidu.com 就可以打开百度,这是因为知道了域名,域名在DNS服务器上映射到了对应的公网IP,域名是和ip地址绑定的,访问www.xxx.com 等于访问 公网IP,可以使用cmd的ping命令去看返回ip地址。每次发送信息到百度服务器返回的地址其实是nat的地址和端口,然后由nat转发给你的内网地址和端口并生成记录,记录类似于: (nat地址:端口——内网地址:端口)。因为A,B都是内网,无法直接通信,所以需要一个公网服务器 来记录A,B的nat地址和端口。

  • 搭建内网穿透工具-ngrok

    由于某些内部网络的站点需要外部调用或者访问,则需要一个外网能够访问内网的方法,而内网穿透就是这个方法之一。

  • NAT打洞(udp打洞和tcp打洞)

    记录udp和tcp打洞过程中的重要技术点。

  • hcip(p2p网络与虚拟专线)

    网络类型 --- 根据数据链路层所使用的协议及规则来进行划分 1.P2P网络 --- 点到点网络 2.MA网络 --- 多点接入网络 --- BMA 广播型多点接入网络 --- NBMA 非广播型多点接入 数据链路层协议 以太网协议 ---- 封装数据帧是,需要假如源MAC地址和目标MAC地址 (MAC地址是以太网所独有) 原因:利用以太网建立的二层网络中可以包含多个(两个或两个以上)接口,每个以太...

  • HCIP D3

    HCIP3

  • 永久免费内网穿透,使用超简单的方式搭建,内含核心打洞代码

    内网穿透,即NAT穿透,是一个网络连接时术语,当计算机处于局域网内时,如家庭路由器、公司内部路由器等,出门在外就会受限于外网,不能直接访问,这时候通过内网穿透,就能让外网的电脑找到处于内网的电脑,将内网下应用映射到外网。 当下,内网穿透具有十分广泛的应用:对于个人用户来说,内网穿透可以让他们在外出时还能直接访问处于家庭路由器的电脑,进行相关操作;对于企业用户来说,内网穿透就具有更多的意义,...

  • BGP基础详解(HCIP)

    BGP基础详解

  • 分享一个支持TCP&UDP穿透的商业应用的P2P组件

    这些源码非常有参考价值, 实际的商业应用可以借鉴。 注意, 虽然是简化版本, 但udp&tcp穿透, 数据交互是完全完整的, 穿透这块经过本人几个项目的 总结, 代码已经变得非常简单, 全部穿透的逻辑代码不到1000行(有的项目P2P模块上W行代码^-^)。 实际游戏运营的穿透率是70%左右。 编译和运行 1. 先编译include/herm. 2. 编译tcp_relayd&ud

  • P2P:UDP和TCP穿透NAT

    1. NAT 简介 NAT(Network Address Translation ,网络地址转换) 是一种广泛应用的解决IP 短缺的 有效方法, NAT 将内网地址转和端口号换成合法的公网地址和端口号,建立一个会话,与公网主机进行通信。 1.1. NAT 分类 NAT 从表面上看有三种类型:静态 NAT 、动态地址 NAT 、地址端口转换 NAPT 。   (1 )静态NAT :静态地

  • NAT穿透技术详解(udp打洞精髓附代码)

    以前自己写的代码都只是在本地进行c/s通信,今天想写一个可以跨越外网的c/s通信,这里我就用udp实现一个点对点的不同外网的通信。用到的技术就是nat穿透技术,这里最直接使用的就是udp打洞技术。文中如有表述不清楚,欢迎提问。如果你需要nat穿透技术的详解点这里:nat穿透浅析需要的设备:一个已知的外网服务器S(ip+port),两个位于不同外网的客户端A, B首先要知道udp打洞的流程:1.A客...

  • FRP的UDP协议内网穿透方案/穿透多个内网机器/账户无效问题

    通过Frp以UDP方式远程访问内网机器

  • P2P 之 UDP穿透NAT的原理与实现(附源代码)

    原创:shootingstars参考:http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt论坛上经常有对P2P原理的讨论,但是讨论归讨论,很少有实质的东西产生(源代码)。呵呵,在这里我就用自己实现的一个源代码来说明UDP穿越NAT的原理。首先先介绍一些基本概念: NAT(Network Addre

Global site tag (gtag.js) - Google Analytics