StackOverflow 上面最流行的 7 个 Java 问题!

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

image.png

StackOverflow发展到目前,已经成为了全球开发者的金矿。它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西。


这篇文章是在我们审阅了StackOverflow上最流行的Java问题以及答案后从中挑出来的。即使你是一个有丰富经验的开发者,也能从中学到不少东西。


一、分支预测

问题链接:


https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array


StackOverflow上最多投票的一个Java问题是:为什么处理一个排序数组要比非排序数组快的多。


为了回答这个问题,你需要使用分支预测(branch prediction)。分支预测是一种架构,旨在通过在真实的路径发生前猜测某一分支的下一步来提升处理过程。


分支在这里即一个if语句。这样的话,如果是一个排序数组,那么分支预测将会进行,否则不会进行。


StackOverflow上的一个回答者,链接:


http://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array/11227902#11227902


试图使用铁路和火车来简单介绍这个概念。假设你在铁轨连接处要决定火车要走哪条路,你会选择左边还是右边?


你可以拦住火车,然后问司机该往哪里,但是这样会让整个过程变慢。因此你只能去猜正确的方向,那么如何去猜呢?最好的办法就是通过观察目前这个火车每次经过时的路线,推测出正确的方向。


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


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


二、Java中的安全

问题链接:


http://stackoverflow.com/questions/8881291/why-is-char-preferred-over-string-for-passwords-in-java


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


其实这里不用惊讶-这是一个安全问题。String是不可变的,意味着一旦它被创建了,那么你就不可能去修改它。


这也意味着在GC之前,你对这些数据不能做任何处理。因此,只要有人能够访问你的内存,那么String就有可能被他获取到。


这也就是为什么要使用char数组。你可以显示地清除数据或者覆盖它。这样密码这种敏感数据即使GC还没有进行也不会再在系统留下痕迹。另外,关注微信公众号:Java技术栈,在后台回复:Java,可以获取我整理的 N 篇 Java 教程,都是干货。


三、异常

问题链接:


http://blog.takipi.com/the-top-10-exceptions-types-in-production-java-applications-based-on-1b-events/


即使很多开发者倾向于忽略对受检异常的处理,StackOverflow上仍然有很多关于异常的问题。


其中一个最流行的问题是:什么是NullPointerException,我该怎么处理它?对此,我们并没有感到惊讶,因为这个问题也是在生产环境的Java应用中排名第一的异常。


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


四、为什么这段代码使用随机字符串打印出了”hello world”

问题链接:


http://stackoverflow.com/questions/15182496/why-does-this-code-using-random-strings-print-hello-world


这个问题给出了下面的代码,并打印出了”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();
}

其实,选择一组随机的整数并不是随机的。给定一个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指出了这一点,链接:


http://stackoverflow.com/a/6841479/5982245


在时区数据库项目2014版中,这个改变的时间点改到了1900-12-31,因此成了344秒的差距。另外,关注微信公众号:Java技术栈,在后台回复:Java,可以获取我整理的 N 篇 Java 教程,都是干货。


六、无法被捕获的ChuckNorrisException

问题链接:


http://stackoverflow.com/questions/13883166/uncatchable-chucknorrisexception


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


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


http://stackoverflow.com/a/13883510/5982245


七、哈希表

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


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


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


http://zeroturnaround.com/wp-content/uploads/2016/04/Java-Collections-cheat-sheet.png

image.png

八、总结

对于Java,其实关键的不在于你懂多少,而是在于你可以一直学到更多的东西。

StackOverflow不仅在code上的一些问题可以帮助我们,也有助于我们回过头来去深入地学习一些我们已经知道的知识。

相关文章
|
架构师 安全 Java
StackOverflow 上面最流行的 7 个 Java 问题!
StackOverflow发展到目前,已经成为了全球开发者的金矿。它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西。
|
Java 数据安全/隐私保护
Stackoverflow上人气最旺的10个Java问题
1、 为什么两个(1927年)时间相减得到一个奇怪的结果? (3623个赞) 如果执行下面的程序,程序解析两个间隔1秒的日期字符串并比较: 01 public static void main(String[] args) throws ParseException { 02     SimpleDate
1421 0
|
Web App开发 Java
Sun Java Web Server version 7.0 update 7 remote stack overflow exploit
/* Sun Java Web Server Exploit * Tested on: * Sun Java Web Server 7.
834 0
|
18天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
80 17
|
28天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
14天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
30天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
30天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。

热门文章

最新文章