首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 開發者最易犯的 10 個錯誤:從 ArrayList 到 String 不可變性

     編輯:Java 綜合教學

前言

基於 GitHub 開源項目、Stack Overflow 問題及 Google 搜索分析,總結 Java 開發中高頻且隱蔽的 10 個錯誤,助你避坑提效。

1. Arrays.asList() 返回的不是 java.util.ArrayList

// 錯誤:返回 Arrays 內部類,不支持 add/remove
List<String> list = Arrays.asList(arr);

// 正確:包裝成真正的 ArrayList
ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(arr));

內部類僅實現 set/get/contains,大小固定,調用 add 拋出 UnsupportedOperationException。

2. 判斷數組包含值時多此一舉轉 Set

// 低效:轉 Set 額外開銷
Set<String> set = new HashSet<>(Arrays.asList(arr));
return set.contains(targetValue);

// 推薦:直接用 List.contains 或循環
Arrays.asList(arr).contains(targetValue);
// 或
for (String s : arr) if (s.equals(targetValue)) return true;

3. 循環中刪除 List 元素導致索引錯位

// 錯誤:刪除後 size 變小,索引指向錯誤元素
for (int i = 0; i < list.size(); i++) list.remove(i);

// 錯誤:foreach 底層用迭代器,刪除拋 ConcurrentModificationException
for (String s : list) if (s.equals("a")) list.remove(s);

// 正確:使用 Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (s.equals("a")) it.remove();
}

foreach 編譯器在刪除前調用 next(),導致異常。

4. HashTable vs HashMap:同步開銷多數場景不需要

HashTable 所有方法同步,性能較差。非多線程環境首選 HashMap;需線程安全用 ConcurrentHashMap。

5. 使用原始類型跳過泛型檢查

// 危險:raw type 繞過編譯期類型檢查
public static void add(List list, Object o) { list.add(o); }
List<String> list = new ArrayList<>();
add(list, 10); // 運行時拋 ClassCastException

區別:Set (raw)、Set<?> (無界通配符)、Set<Object> (具體類型)。

6. 過度使用 public 字段破壞封裝

盡可能降低訪問級別:private > default > protected > public。提供 getter/setter 控制訪問邏輯。

7. ArrayList vs LinkedList 選型盲目

  • 頻繁增刪、少隨機訪問 → LinkedList
  • 頻繁隨機訪問、少增刪 → ArrayList

兩者性能差異巨大,必須根據訪問模式選擇。

8. 可變與不可變對象選擇失衡

  • 不可變優點:線程安全、簡單、可共享
  • 缺點:頻繁修改產生大量中間對象,GC 壓力大
  • 字符串拼接用 StringBuilder(可變)
  • 需收集多結果或大集合排序/過濾時,可變對象更高效

9. 父類無無參構造導致子類編譯失敗

class Super { public Super(String v) {} }
class Sub extends Super {} // 編譯錯誤:隱式 super() 找不到無參構造

// 修復三選一:
// 1. 父類加無參構造
// 2. 移除父類有參構造
// 3. 子類显式調用 super(value)

10. 字符串字面量 vs new String()

String a = "abcd", b = "abcd";      // 常量池同一對象
String c = new String("abcd");      // 堆上新對象
String d = new String("abcd");
a == b  // true
c == d  // false
a.equals(b) // true
c.equals(d) // true

字面量走常量池複用,new 總在堆創建新對象。

總結

這 10 個錯誤涵蓋集合、泛型、併發、內存模型、語言特性,理解背後原理比記住規則更重要。持續重構、Code Review、閱讀源碼是提升的最佳路徑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved