當前位置:
首頁 > 知識 > Java開發中如何正確踩坑?

Java開發中如何正確踩坑?


為什麼說一個好的員工能頂 100 個普通員工

我們的做法是,要用最好的人。我一直都認為研發本身是很有創造性的,如果人不放鬆,或不夠聰明,都很難做得好。你要找到最好的人,一個好的工程師不是頂10個,是頂100個。所以,在核心工程師上面,大家一定要不惜血本去找,千萬不要想偷懶只用培養大學生的方法去做。最好的人本身有很強的驅動力,你只要把他放到他喜歡的事情上,讓他自己有玩的心態,他才能真正做出一些事情,打動他自己,才能打動別人。所以你今天看到我們很多的工程師,他自己在邊玩邊創新。所以,找最好的人,要給他做他喜歡和擅長的事情。研發人員千萬不要去管太嚴,一管就「死」了。工程師很討厭跟規章制度打交道,作彙報他都很煩,大家不要管他,讓用戶去管他。他做好了一個產品,用戶表揚他,這個大神多牛逼。他做不好了,用戶罵他,他自己趕緊去改。

再談阿里巴巴 Java 開發手冊

之前在這個手冊剛發布的時候看過一遍,當時感覺真是每個開發者都應該必讀的一本手冊,期間還寫過一篇關於日誌規約的文章:《下一個項目為什麼要用 SLF4J》,最近由於在總結一些我們日常開發中容易忽略的問題,可能是最低級的編碼常見問題,往往這也是最最容易忽略的,所以,又重新看了一遍這個手冊,好像最近它也更新到了 1.2 版本。

這個手冊目的就是讓我們儘可能少踩坑,杜絕踩重複的坑。我接下來就打算試著寫一些「坑」出來,來看看我們如何一不留神踩坑的,以及如何用正確的姿勢跳出坑。


隨隨便便寫出 NPE

首先聲明一個 User 對象,接下來所有代碼可能都會用到這個對象做演示,在下面將不在贅述。很簡單,不上代碼,上圖片:

Java開發中如何正確踩坑?

1.自動解箱拋 NPE

代碼只有一行,再簡單不過了:int method() { return new User().getId(); }

Java開發中如何正確踩坑?

踩坑姿勢:包裝類型為 null 時,進行自動轉換為基本數據類型報錯。

解決方案:返回之前進行判斷與處理或者改為相同類型。

2.級聯調用易產生 NPE

這段代碼有點容易迷惑人,因為它進行了集合元素的 isEmpty 判斷,按說不會出問題了吧。看代碼:

Java開發中如何正確踩坑?

不廢話,看運行結果:

Java開發中如何正確踩坑?

沒錯,還是報錯了。

踩坑姿勢:其實就是儘管你在之前做了對象不為空的判斷,但你並不能保證對象中的值不為空,而且這時候去級聯調用就會拋 NPE 。

手冊中關於 NPE 的描述:


防止 NPE 是調用者的責任。即使被調用方法返回空集合或者空對象,對調用者來說,也並非高枕無憂,必須考慮到遠程調用失敗、序列化失敗、運行時異常等場景返回 null 的情況。

集合里的元素即使 isEmpty,取出的數據元素也可能為 null。

級聯調用 obj.getA().getB().getC();一連串調用,易產生 NPE

3.關於 Equals

這是日常開發中用於相等比較使用最多的方法了吧,因為當年誰沒被 == 坑過阿。現在一般我們都會這麼寫:user.getName().equals("mafly");

Java開發中如何正確踩坑?

踩坑姿勢: 一不小心使用了 null 值調用了 Equals 方法。

解決方案: 很簡單咯,這麼寫:"mafly".equals(user.getName());


equals 方法容易拋空指針異常,應使用常量或確定有值的對象來調用 equals。

4.Map 下的 NPE

Map 應該是我們開發中使用最頻繁的了,最常用的可能有 HashMap、ConcurrentHashMap 這倆了,可能會一不留神寫出這樣的代碼:

Java開發中如何正確踩坑?

踩坑姿勢: 可能我們知道 ConcurrentHashMap 的 K/V 都不能為空,但我們有時候並不知道傳進來的值是否為空。

解決方案: 設置時做下檢驗,對它的特性正確理解及使用。


由於 HashMap 的干擾,很多人認為 ConcurrentHashMap 是可以置入 null 值,而事實上,

存儲 null 值時會拋出 NPE 異常

Map 類集合 K/V 能不能存儲 null 值的情況,如下表格:


集合類 Key Value Super 說明
Hashtable 不允許為 null 不允許為 null Dictionary 線程安全
ConcurrentHashMap 不允許為 null 不允許為 null AbstractMap 分段鎖技術
TreeMap 不允許為 null 允許為 null AbstractMap 線程不安全
HashMap 允許為 null 允許為 null AbstractMap 線程不安全


簡單聊聊常用的集合

5.foreach 遍歷集合刪除元素

大家應該都知道,在遍歷集合時對元素進行 add/remove 操作要使用 Iterator,使用 for 循環時會報錯,一定會報錯嗎?看代碼:

Java開發中如何正確踩坑?

應該會報錯的吧?因為在 for 循環中移出了元素,如果你運行了就會驚訝的,輸出如下:

Java開發中如何正確踩坑?

不解釋其中原因了,不管是不是倒數第二個元素才沒問題,我們依然要注意不要在 foreach 循環里進行元素的 remove/add 操作。remove 元素請使用 Iterator 方式(代碼第二種),如果並發操作,需要對 Iterator 對象加鎖。

6.Arrays.asList() 數組轉換集合

這個工具類應該都用過,可以很方便的把數組轉換為集合,直接看結果吧:

Java開發中如何正確踩坑?

踩坑姿勢: Arrays.asList()把數組轉換成集合時,不能使用其修改集合相關的方法,它的 add/remove/clear 方法會拋出 UnsupportedOperationException 異常。 asList() 的返回對象是一個 Arrays 內部類,並沒有實現集合的修改方法。

解決方案: 在轉換之前操作咯。還需要注意一點,在你轉換後,再對數組的值進行修改時,集合也會跟著變哦(注釋掉的代碼)。

7. toArray() 集合轉換數組

當我們需要把一個集合轉換為數組時,往往會調用 toArray() 方法,如果你用的是無參的這個可以嗎?

Java開發中如何正確踩坑?

當然不可以啦!會報 ClassCastException 異常。

踩坑姿勢: 直接使用 toArray() 無參方法返回值只能是 Object[]類,若強轉其它類型數組將會拋異常。

解決方案: 使用 T[] toArray(T[] a); 有參數這個方法,代碼如下:

Java開發中如何正確踩坑?

8. subList 的使用

集合中的 subList 是用於來返回某一部分的視圖內容的,可能我們不是很常用,但是其中有好多坑的,直接看代碼:

Java開發中如何正確踩坑?

Java開發中如何正確踩坑?

這次我們從輸出來看上面的所有關於 subList 的代碼。

  • 18行: 當你原始集合大小沒有那麼大時,毫無疑問拋異常。

  • 20-21行:得到一個新的集合,我們往新集合中增加一條數據。

  • 23-26行:遍歷原始集合,竟然 size=2 了,而且往新集合中增加的數據存在與原始集合。

  • 28-31行:移除新集合中一條數據,遍歷新集合。

  • 33-37行:原始集合增加一條數據並遍歷。

  • 40-42行:遍歷新集合,拋出 ConcurrentModificationException 異常。

從上述代碼中,我們應該可以得出如下結論:返回的新集合是靠原來的集合支持的,修改都會影響到彼此對方。在 subList 場景中,高度注意對原集合元素個數的修改,會導致子列表的遍歷、增加、刪除均產生異常。


先總結一下

寫到這只是其中關於異常部分的一些坑吧,還有另外一些令人異常驚訝的「我的天吶」的問題,由於篇幅太長了點,感覺不能再寫下去了,過兩天再接著寫吧。

異常真的是一個有意思的問題。


學習Java的同學注意了!!!

學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入Java學習交流群495273252,我們一起學Java!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java團長 的精彩文章:

《實戰java高並發程序設計》源碼整理及讀書筆記
JavaSE的自動裝箱和自動拆箱
程序員如何選擇未來的職業路線
Java中String通過引用傳遞問題詳細解析
Java面向對象總結

TAG:Java團長 |