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還沒有進行也不會再在系統留下痕迹。
三、異常
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”。
其實,選擇一組随機的整數并不是随機的。給定一個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
按說上面的代碼最後的結果應該是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秒的差距。
六、無法被捕獲的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制作。連結: