前言
上一篇博文已經是3個月以前的了,最近比較忙沒有時間整理技術文檔。在空閑的時間把《Java解惑》這本書讀了一遍,感覺里面的挺有意思的,推薦一下。其實里面也沒有什么高難度的東西,都是比較基礎而又常常被忽略的知識點。在項目中可能用到的時候不多,但是對於分析問題卻有很大的幫助。突然覺得自己的java基礎很弱。下面收集了一些問題,希望和大家交流。
1、《Java解惑》中的一個問題。
這類問題基本上都是數值精度方面的。書中有這樣一個例子:
public class Main2 { public static void main(String[] args) { System.out.println(2.00-1.10); } }
不經過分析就直接認為輸出:0.9。最關鍵的不是結果是多少,而是過程。我意識到需要看看double的數據是如何存儲的,當然也復習一下十進制轉二進制。這些都太過於底層,但是必須了解才能正確地分析問題。
書中的解釋:“1.1不能被精確的表述為一個double”。
這樣的解釋我覺得不好,如果這么解釋的話,那么2.00+1.10是不是也可以這么解釋呢?那為何結果又是精確的呢?那么2.00f-1.10f為何又沒有問題,1.10f也不能精確被精確表述為一個float?網上也沒有看到合理的解釋,再看看基礎吧。
2、技術群里面的一個問題。
考查synchronized 基礎。
public class Main3 extends Thread { public static int ticket = 10000; public static void main(String[] args) { while (ticket > 0) { Thread thread = new Main3(); thread.start(); } } @Override public void run() { subTicket(); } private synchronized void subTicket() { if (ticket > 0) { System.out.print(ticket-- + "\t"); } if (ticket % 10 == 0) { System.out.println(); } } }
看上去感覺是線程安全的,但實際卻不是線程安全的,打印結果可以說明這個問題。仔細分析以后發現subTicket()方法確實不是同步的,雖然用了synchronized關鍵字。原因很簡單他只是對對象進行了同步,但是方法里面卻訪問了類變量,所以這個方法應該改成對類進行同步,就這么簡單。我總結了一下這個問題分析錯誤主要是因為對synchronized關鍵字不熟悉,說穿了就是基礎不扎實,更主要的是太粗心,尤其是看到簡單的問題就更粗心了。
3、《深入理解java虛擬機》中的一個錯誤。
下面是書中的程序。
public class Main2 { static { if (true) { System.out.println(Thread.currentThread() + " init"); while (true) { } } } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread() + " start"); Main2 main2 = new Main2(); System.out.println(Thread.currentThread() + " over"); } }; Thread r1 = new Thread(runnable); Thread r2 = new Thread(runnable); r1.start(); r2.start(); } }
我分析以后的打印結果是:Thread[main,5,main] init。但是書中並不是這么說的,反正是錯的。我在群里咨詢、在網上也找了很久確定書中的分析的確是錯的,而且這程序跑起來也驗證了我的想法。當遇到這類很深奧的書籍時,即使它描述錯了也不敢懷疑,總是找自己的問題。教訓就是“盡信書不如無書”。其實信書不信自己的根本就是基礎弱。提高基礎刻不容緩啊。
4、OOM問題的根源。
了解了JVM的垃圾回收機制以后覺得以前對這一塊的了解太粗略了,更大程度上還有些理解是不正確的,如果要分析OOM這類問題,那么需要先對垃圾回收機制進行全面深入了解。不同的虛擬機的垃圾回收不盡相同。由於本人做Android開發,但是很可惜的是google上面並沒有說明Android使用是何種虛擬機(可能是我沒有找到,有知道的朋友希望給個提示)。以前的程序有過OOM問題,當然是因為沒有正確理解到垃圾回收,甚至是根本就沒有這個概念。所以再次強調基礎。
總結:基礎很重要。再高層的開發最終都是通過這些基礎實現的,不外乎用了一些設計模式。深入理解基礎才是硬道理,當然深入JVM理解也是有必要的。除了具備基礎以外,細心是程序員應該具備的素養。進一步提高自己吧。
PS:文中有不妥的地方請讀者指出,歡迎交流。