对开发人员来说, StackOverflow 就像一个金矿对具体的问题, 它能帮我们找到最有用的答案, 并且我们也可以从上面学习新的知识
下面的内容, 通过这些最常见的 JAVA 问题与答案, 并着重的标记出我们找到的精华问题即便你是一个经验丰富的开发人员, 这些也是值得去学习的
JAVA 问题纵览
JAVA 是 StackOverflow 上 第二流行的标签 , 有超过 100 万个问题与 JAVA 有关仅在上个礼拜, 就有 4600 个问题被提出, 毫无疑问这里是开发者们最大也是最为活跃的线上社区
此信息同样也出自 StackOverflow 2016 年的开发者调查中 ,56033 名开发者被问到关于开发语言的选择, JAVA 是第三位因为在市场上 JAVA 占据着主导, 因此我们估计读者也曾经有那么一两次的去访问 StackOverflow 来寻找答案但是, 即使你随意的在 StackOverflow 上闲逛, 也会发现很多有趣的问题, 下面让我们来看看这些精心选出的问题
分支预测
在 StackOverflow 上最经常被问到的一个问题就是 为什么处理一个排序过的数组比一个未排序的数组要快 ? 回答这样的问题, 你得了解分支预测
分支预测是一种期望可以提升应用流程的架构, 旨在一条路径在真正被执行前就可以被提前的猜出当然它不仅仅是一个完全意义上的猜测, 而是一个有目的性的猜测
分支在这里就是一个 IF 语句在此情况下, 如果数组是排序过的, 分支预测将起作用, 不然则无法工作 Mysticial 试着用一种简单的方式来解释这个问题, 以铁路和火车为例子想像一下, 你驾驶火车来到一个交汇点, 接下来你需要决定火车走哪条线你会选择左还是右? 当然, 你也可以停下火车问问司机哪一条路是正确的, 但是这却会降低整个火车运行的速度, 并让火车的行进过程变的更加复杂你也可以猜一下, 但是你如何确保你猜的一定是对的呢? 了解下这趟火车之前的司机都是怎么做的, 并且知道在此之前他们都是如何选择道路的, 这是一个非常好的主意
这就是分支预测: 找到模式并且使用他们
不幸的是, 多数情况下能问出这样问题的多半是一个失效的分支预测的受害者由于分支没有可识别的模式, 想要去猜测就真的只能是一个随机的猜测了
JAVA 的安全性
另一个流行的 JAVA 问题是为什么在 JAVA 的密码管理中, 更倾向去使用 char[]而不是 String? 更具体一些的问法是: 为什么在 JAVA Swing 中的密码输入框方法是: getPassword(return char[]), 而不是 getText(return String)
毫无意外的, 这里是一个安全问题因为 String 是不可变的, 这意味着你一旦创建了它则无法修改同样也意味着在 GC 前你无法彻底的删除掉它在某些情况下, 如果有人黑进了你的内存, 那么被保存成 String 的密码则可以被人获取的
这就是为什么 你需要使用字符数组你可以在使用完后显式的清除它, 或者你也可以用其他的别的东西去覆盖它这样敏感的信息就不会在系统的其他地方出现, 即使此时 GC 还没有启动
异常
即使有很多开发人员会忽略异常检查, 但是依然有很多问题是关于 JAVA 异常的在你的代码中这是一个值得引起你注意的问题, 忽略它并不能使它消失
最常见的一个问题是什么是 NullPointerException, 并如何消除它, 看到这样的问题有如此多的人问, 我们毫不惊奇在 JAVA 的生产环境中, 空指针异常也确实是排名第一的异常类型
Takipi 介绍了一种检查空指针异常或者其他异常的一种新的方法
一些有趣的问题
StackOverflow 上总有些有趣的问题可以教授你一些新的知识我们选了如下内容
为何如下代码可以使用 Random String 来打印出 Hello World?
- 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();
- }
如果是一组选择好的随机数, 那么事实上他们并不是真正随机的随机数的算法是根据种子参数来进行计算的,(当前则是 -229985452 或者 -147909649)每一次当申请一个随机数的时候, 它会根据相同的随机数种子来生成一个相同的值 打印出 hello world
Random(-229985452).nextInt(27)
前六个随机数是: 8,5,12,12,15,0.
Random(-147909649).nextInt(27)
前六个随机数是: 23,15,18,12,4,0
当你将这些数字转换成字符的时候
- 104 > h
- 101 > e
- 108 > l
- 108 > l
- 111 > o
- 119 > w
- 111 > o
- 114 > r
- 108 > l
- 100 > d
你将获得 hello world
为何两个相差一秒的时间相减会有奇怪的结果
- 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);
- }
- Java version:
- java version "1.6.0_22"
- Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
- Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
- Timezone(TimeZone.getDefault()):
- sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
- offset=28800000,dstSavings=0,
- useDaylight=false,
- transitions=19,
- lastRule=null]
- Locale(Locale.getDefault()): zh_CN
输出结果是 353 (译者注: 在 JDK 1.8 上未能重现这个问题, 原题注的 JAVA 版本是 1.6)
很显然只有一秒的差距, 但是得到的结果确实 353, 一个最基本的解释是: 时区的问题在 1927 年 12 月 31 日, 上海的时区往后移动了 5 分钟 52 秒
值得一提的是, 如果你尝试着去运行这段代码, 可能会有不同的结果根绝 Time Zone Database Project 2014 项目这一时区的改变被挪到了 1900-12-31,, 因此可能有个 343 秒的一个变化
不可捕获的 ChuckNorrisException
有一些问题是关于: 有没有一种异常是可以被抛出的, 但是没人可以捕获它, 应用会崩溃么? 或者这样的问题也可以变成有没有代码可以让 java.lang.ChuckNorrisException 变成无法捕获的异常?
简单的回答是: 这是可能的, 但是那是有一些前提的你可以编译一段代码抛出 ChuckNorrisException, 然后再定义一个 ChuckNorrisException 类, 但是这个类却不在运行时继承自 Throwable 但是仅仅如此还是不够的, 你必须禁用二进制码检查 StackOverflow 上有一个答案可以提供这样的一个完整例子 (点击访问)
如果你喜欢类似的问题, 你可以查看 Java Deathmatch 游戏
Hash Maps
在 StackOverflow 上还有一种常见的问题是与 hash maps 有关的很多开发人员都想知道集合类中的不同类的区别, 以及在何时用哪一个
核心的问题是迭代的顺序在 HashMap 中是没有任何与顺序有关的信息的, 并且元素的顺序在你插入集合的时候就已经被改变了在 TreeMap 中, 你可以得到一个已被排序的集合, 在 LinkedHashMap 中, 你可以得到一个先进先出 (FIFO) 的集合
如果你还有疑惑, 我们的朋友 Rebel Labs 制作了 一个图 来解释这些集合间的关系
结束语
无论你对 JAVA 有多了解, 总有些的知识是需要你学习的 StackOverflow 不仅仅是问问题的地方, 也是可以彻底的学习新知识的地方
来源: http://www.tuicool.com/articles/uUfquaA