基於 GitHub 開源項目、Stack Overflow 問題及 Google 搜索分析,總結 Java 開發中高頻且隱蔽的 10 個錯誤,助你避坑提效。
// 錯誤:返回 Arrays 內部類,不支持 add/remove
List<String> list = Arrays.asList(arr);
// 正確:包裝成真正的 ArrayList
ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(arr));
內部類僅實現 set/get/contains,大小固定,調用 add 拋出 UnsupportedOperationException。
// 低效:轉 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;
// 錯誤:刪除後 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(),導致異常。
HashTable 所有方法同步,性能較差。非多線程環境首選 HashMap;需線程安全用 ConcurrentHashMap。
// 危險: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> (具體類型)。
盡可能降低訪問級別:private > default > protected > public。提供 getter/setter 控制訪問邏輯。
兩者性能差異巨大,必須根據訪問模式選擇。
class Super { public Super(String v) {} }
class Sub extends Super {} // 編譯錯誤:隱式 super() 找不到無參構造
// 修復三選一:
// 1. 父類加無參構造
// 2. 移除父類有參構造
// 3. 子類显式調用 super(value)
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、閱讀源碼是提升的最佳路徑。