Java開發人員易犯錯誤Top10

來源:互聯網
上載者:User

標籤:

本文總結了Java開發人員經常會犯的前十種錯誤清單。

Top1. 數群組轉換為數組列表

將數群組轉換為數組列表,開發人員經常會這樣做:

 

[java] view plaincopy 
  1. List<String> list = Arrays.asList(arr);  

 

Arrays.asList()將返回一個數組內部是私人靜態類的ArrayList,這不是java.util.ArrayList類,java.util.Arrays.ArrayList類有set()、 get()、 contains()方法,但是沒有任何加元素的方法,因此它的大小是固定的。你應該這麼做來建立一個真正的數組:

 

[java] view plaincopy 
  1. ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));  

 

ArrayList的建構函式能夠接受一個集合類型,這也是java.util.Arrays.ArrayList的超級類型。

Top2. 檢查一個數組包含一個值

開發人員經常這麼做:

 

[java] view plaincopy 
  1. Set<String> set = new HashSet<String>(Arrays.asList(arr));  
  2. return set.contains(targetValue);  

 

代碼可以工作,但是沒有必要首先轉換列表到Set,轉換一個列表到一個Set需要額外的時間。因此你可以把它簡化為:

 

[java] view plaincopy 
  1. Arrays.asList(arr).contains(targetValue);  

 

 

[java] view plaincopy 
  1. for(String s: arr){  
  2.     if(s.equals(targetValue))  
  3.         return true;  
  4. }  
  5. return false;  

 

第一個比第二個更具可讀性

Top3. 在一個迴圈中從一個列表裡刪除一個元素

考慮下面刪除元素的代碼在迭代中的結果:

 

[java] view plaincopy 
  1. ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));  
  2. for (int i = 0; i < list.size(); i++) {  
  3.     list.remove(i);  
  4. }  
  5. System.out.println(list);  

 

輸出是:

 

[java] view plaincopy 
  1. [b, d]  

 

該方法有一個嚴重的問題,當一個元素被刪除時,列表收縮的大小以及指標改變了。所以想要在迴圈內利用指標刪除多個元素是無法正常進行的。

這種情況下使用迭代器才是正確的方法,foreach迴圈在Java中的工作像是一個迭代器,但實際上並不是,考慮下面的代碼:

 

[java] view plaincopy 
  1. ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));  
  2.    
  3. for (String s : list) {  
  4.     if (s.equals("a"))  
  5.         list.remove(s);  
  6. }  

 

它會報出ConcurrentModificationException異常。

相反下面這個就可以正常工作。

 

 

[java] view plaincopy 
  1. ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));  
  2. Iterator<String> iter = list.iterator();  
  3. while (iter.hasNext()) {  
  4.     String s = iter.next();  
  5.    
  6.     if (s.equals("a")) {  
  7.         iter.remove();  
  8.     }  
  9. }  

 

 

.next()必須在.remove()之前被調用。在foreach迴圈中,編譯器將在刪除元素操作之後調用.next(),這也是導致ConcurrentModificationException異常的原因,你可以點擊此處查看ArrayList.iterator()的原始碼。

Top4. Hashtable vs HashMap

根據演算法的常規,Hashtable是對資料結構的稱呼。但是在Java中,資料結構的名稱是HashMap。Hashtable和HashMap關鍵不同之一是Hashtable是同步的。

關於這一點可查看以下兩個連結:

HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap

Map問題Top10

Top5. 使用集合的原始類型

在Java中,原始類型和無限制的萬用字元類型很容易被混淆。以Set為例,Set是原始類型,而Set(?)則是無限制的萬用字元類型。

考慮下面的代碼,以一個原始類型List作為參數:

 

[java] view plaincopy 
  1. public static void add(List list, Object o){  
  2.     list.add(o);  
  3. }  
  4. public static void main(String[] args){  
  5.     List<String> list = new ArrayList<String>();  
  6.     add(list, 10);  
  7.     String s = list.get(0);  
  8. }  

 

該代碼會拋出一個異常:

 

[java] view plaincopy 
  1. Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String  
  2.     at ...  

 

使用原始類型集合是危險的,因為原始類型集合跳過了泛型型別檢查,也不安全。Set、Set<?>和Set<Object>之間有很大的不同。詳細可查看

Raw type vs. Unbounded wildcard和Type Erasure。

Top6. 存取層級

開發人員經常對類域使用public,這很容易通過直接引用獲得域值,但這是一個非常糟糕的設計。根據經驗來說是給予成員的存取層級越低越好。

詳細情況可點擊查看Java中成員存取層級:public、protected、private

Top7.ArrayList VS LinkedList

如果你不知道ArrayList和LinkedList之間的區別時,你可能會經常的選用ArrayList,因為它看起來看熟悉。然而它們之間有巨大的效能不同。簡單的來說,如果有大量的添加/刪除操作,並且沒有很多的隨機存取操作時,LinkedList應該是你的首選。如果您對此不是很瞭解的話,點此此處查看更多關於它們效能的資訊。

Top8. Mutable VS Immutable

Immutable對象有很多優勢,比如簡單、安全等等。但它要求每一個不同的值都需要有一個不同的對象,而太多的對象可能會導致垃圾收集的高成本。所以對Mutable和Immutable的選擇應該有一個平衡點。

一般來說,Mutable對象用於避免產生過多的中間對象,經典的例子是串連大量的字串數。如果你使用Immutable字串,那麼會產生很多符合垃圾收集條件的對象。這對CPU是浪費時間和精力的,當其可以使用Mutable對象作為正確的解決方案。(如StringBuilder)

 

[java] view plaincopy 
  1. String result="";  
  2. for(String s: arr){  
  3.     result = result + s;  
  4. }  

 

這裡還有一些其他Mutable對象可取的情況。例如mutable對象傳遞到方法中允許你在不跳過太多文法的情況下收集多個結果。另一個例子是排序和過濾,你可以構建一個帶有原有集合的方法,並返回一個已排序的,不過這對大的集合來說會造成更大的浪費。

推薦閱讀:為什麼字串是Immutable?

Top9. Super和Sub建構函式


這個編譯錯誤是因為預設的Super建構函式是未定義的。在Java中,如果一個類沒有定義一個建構函式,編譯器會預設的為類插入一個無參數建構函式。如果一個建構函式是在Super類中定義的,這種情況下Super(String s),編譯器不會插入預設的無參數建構函式。

另一方面,Sub類的建構函式,無論帶不帶有參數,都會調用無參數的Super建構函式。

編譯器在Sub類中試圖將Super()插入到兩個建構函式中,但是Super預設的建構函式是沒有定義的,編譯器才會報錯。如何解決這一問題?你只需在Super類中添加一個Super()建構函式,如下所示:

 

[java] view plaincopy 
  1. public Super(){  
  2.     System.out.println("Super");  
  3. }  

 

或移除自訂的Super建構函式,又或者在Sub函數中添加super(value)。

這方面想瞭解更多的可以點擊此處查看。

Top10. ""或建構函式?

字串可以通過兩種方式建立:

 

[java] view plaincopy 
  1. //1. use double quotes  
  2. String x = "abc";  
  3. //2. use constructor  
  4. String y = new String("abc");  

 

它們之間有何不同?下面的例子可以給出答案:

 

[java] view plaincopy 
  1. String a = "abcd";  
  2. String b = "abcd";  
  3. System.out.println(a == b);  // True  
  4. System.out.println(a.equals(b)); // True  
  5.    
  6. String c = new String("abcd");  
  7. String d = new String("abcd");  
  8. System.out.println(c == d);  // False  
  9. System.out.println(c.equals(d)); // True  

 

關於它們如何在記憶體中分布的更多細節可以查看《使用""或建構函式建立Java字串》。

Java開發人員易犯錯誤Top10

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.