當前位置:
首頁 > 知識 > Java程序員常犯的10個錯誤

Java程序員常犯的10個錯誤

人非聖賢,孰能無過。都說Java語言是一門簡單的編程語言,基於C++演化而來,剔除了很多C++中的複雜特性,但這並不能保證Java程序員不會犯錯。那麼對於廣大的Java程序員來說,它們最常犯的10個錯誤是什麼呢?本文通過總結出Java程序員最常犯的10大錯誤,可以有效地幫組Java後來者少走彎路,少加班,並寫出更健壯的應用程序。

1. 數組轉ArrayList

為了實現把一個數組轉換成一個ArrayList,很多Java程序員會使用如下的代碼:

Java程序員常犯的10個錯誤

Arrays.asList確實會返回一個 ArrayList對象,但是該類是 Arrays類 中一個私有靜態內部類,而不是常見的 java.util.ArrayList類。這個 java.util.Arrays.ArrayList 類具有 set(),get(),contains()等方法,但是不具有任何添加或移除元素的任何方法。因為該類的大小(size)是固定的。為了創建出一個真正的 java.util.ArrayList,代碼應該如下所示:Java程序員常犯的10個錯誤

我們知道,ArrayList的構造方法可以接受一個 Collection 類型的對象,而我們的 java.util.Arrays.ArrayList 正好也是它的一個子類。實際上,更加高效的代碼示例是:Java程序員常犯的10個錯誤

2. 數組是否包含特定值

為了檢查數組中是否包含某個特定值,很多Java程序員會使用如下的代碼:

Java程序員常犯的10個錯誤

就功能而言,該代碼是正確無誤的,但在數組轉List,List再轉Set的過程中消耗了大量的性能。我們可以優化成如下形式:Java程序員常犯的10個錯誤

或者,進一步優化成如下所示最高效的代碼:Java程序員常犯的10個錯誤

3. 在迭代時移除List中的元素

首先,看一下在迭代過程中移除List中元素的代碼:

Java程序員常犯的10個錯誤

這個示例代碼的輸出結果是:Java程序員常犯的10個錯誤

這個示例代碼中存在一個非常嚴重的錯誤。當一個元素被移除時,該List的大小(size)就會縮減,同時也改變了索引的指向。所以,在迭代的過程中使用索引,將無法從List中正確地刪除多個指定的元素。

你可能知道解決這個錯誤的方式之一是使用迭代器(iterator)。而且,你可能認為Java中的 foreach 語句與迭代器(iterator)是非常相似的,但實際情況並不是這樣。我們考慮一下如下的示例代碼:

Java程序員常犯的10個錯誤

這個示例代碼會拋出來一個 ConcurrentModificationException。我們應該修改成如下所示:Java程序員常犯的10個錯誤

next()方法必須在remove()方法之前被調用。在 foreach 循環中,編譯器使得 remove()方法先於next()方法被調用,這就導致了 ConcurrentModificationException 異常。具體細節可以查看 ArrayList.iterator()的源碼。

4. Hashtable vs HashMap

學習過數據結構的讀者都知道一種非常重要的數據結構叫做 哈希表。在Java中,對應哈希表的的類是 HashMap 而不是 Hashtable。HashMap與Hashtable之間的最核心區別就是:HashMap是非同步的,Hashtable是同步的。

5. 在Collection中使用原始類型

在Java中,很容易把原始類型與無限通配類型混淆。我們舉個Set相關的例子:Set就是原始類型;Set就是無限通配類型。我們看一個使用在List中使用原始類型的例子:

Java程序員常犯的10個錯誤

這個示例代碼會拋出來一個異常:Java程序員常犯的10個錯誤

在Collection使用原始類型是具有很多的類型錯誤風險的,因為原始類型沒有靜態類型檢查。實際上,Set、Set和Set之間具有非常大的差異,

6. 訪問許可權

很多的Java初學者喜歡使用 public 來修飾類的成員。這樣可以很方便地直接訪問和存取該成員。但是,這是一種非常糟糕的編程風格,正確的設計風格應該是儘可能降低類成員的訪問許可權。具體細節,建議參看本站的這篇文章。

7. ArrayList vs LinkedList

很多的Java初學者不明白ArrayList與LinkedList之間的區別,所以,他們完全只用相對簡單的ArrayList,甚至不知道JDK中還存在LinkedList。但是,在某些具體場景下,這兩種List的選擇會導致程序性能的巨大差異。簡單而言:當應用場景中有很多的 add/remove 操作,只有少量的隨機訪問操作時,應該選擇LinkedList;在其他的場景下,考慮使用ArrayList。

8. 可變 vs 不可變

不可變的對象具有非常多的優勢,比如簡單,安全等。但是,對於每一個不同的值,都需要該類的一個對象。而且,生成很多對象帶來的問題就是可能導致頻繁的垃圾回收。所以,在選擇可變類還是不可變類時,應該綜合考慮後再做抉擇。

通常而言,可變對象可以避免創建大量的中間對象。一個非常經典的例子就是鏈接大量的短String對象為一個長的String對象。如果使用不可變String類,鏈接的過程將產生大量的,適合立即被垃圾回收的中間String對象,這將消耗大量的CPU性能和內存空間。此時,使用一個可變的StringBuilder或StringBuffer才是正確的。

Java程序員常犯的10個錯誤

除了上述情況,可變對象在其他場景下可能由於不可變對象。比如,傳遞一個可變的對象到方法內部,利用該對象可以收集多個結果,而不用在多個循環層次中跳進跳出。

9. 繼承中的構造函數

上圖中出現的兩個編譯時錯誤是因為:父類中沒有定義默認構造函數,而子類中又調用了父類的默認構造函數。在Java中,如果一個類不定義任何構造函數,編譯期將自動插入一個默認構造函數到給類中。一旦一個類定義了任何一個構造函數,編譯期就不會插入任何構造函數到類中。在上面的示例中,Super類定義了一個參數類型為String的構造函數,所以該類中只有一個構造函數,不會有默認構造函數了。

&emps;在我們的子類 Sub 中,我們定義了兩個構造函數:一個參數類型為String的構造函數,另一個為午餐的默認函數。由於它們都沒有在函數體的第一行指定調用父類的哪一個構造函數,所以它們都需要調用父類 Super 的默認構造函數。但是,父類 Super 的默認構造函數是不存在的,所以編譯器報告了這兩個錯誤信息。

10. 字元串對象的兩個構建方式

Java中的字元串對象具有兩個常見的創建方式:

Java程序員常犯的10個錯誤

它們之間的區別是什麼呢?我們再看一下如下的代碼:Java程序員常犯的10個錯誤


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

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

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

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


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

談談Java中遍歷Map的幾種方法
其實,我只想安靜的寫寫代碼……
Java線程池入門必備
Java進階自測——面向對象基礎知識掌握了嗎?
自學的程序員如何找到好工作?

TAG:Java團長 |

您可能感興趣

初級Pythoner常犯的7個錯誤
寫開發信常犯的錯誤有哪些?14個常見的開發信cold email錯誤
盤點:出口電商賣家常犯的10個Facebook廣告運營錯誤
盤點那些年運營Facebook常犯的錯誤!
Python 初學者常犯的5個錯誤,布爾型竟是整型的子類
瑜伽練習最常犯的這14個錯誤,你100%犯過!
11.21 練瑜伽最常犯的3個錯誤,大部分人都做過!
初次裝修經常犯的10個錯誤,90%的人都中槍了!
攝影初學者常犯的3個錯誤
瑜伽練習最常犯的這10大錯誤,你100%犯過!
新手程序員經常犯的10個錯,程序員:簡直不要太真實!
追妹子時男生常犯的10個錯誤
Python初學者常犯的簡單錯誤集合與練習
管理者在數據分析上常犯的9個錯誤
女性用「衛生巾」時,常犯的3個錯誤,請對號入座,00後要重視
新生兒護理家長常犯的10個錯誤
瑜伽練習最常犯的這十大錯誤,你100%犯過!
避坑指南:數據科學家新手常犯的13個錯誤
職場中,新人常犯的3個錯誤
瑜伽練習常犯的這11個錯誤,你應該犯過!