造輪子不如用輪子。Java 集合框架提供的 ArrayList 正是解決「動態增刪、自動擴容」痛點的利器。本文通過一個「擊沉戰艦」小遊戲的重構,演示如何用 ArrayList 優雅替代 int[],並順帶梳理泛型、自動裝箱/拆箱、包裝類比較陷阱等核心知識點。
初版遊戲用 int[] localCells 存儲戰艦佔用的格子索引。checkYourself(int guess) 方法中,猜中後未移除該索引,導致同一位置可重複得分。修復方案三選一:
boolean[] hitFlag —— 笨拙且佔空間。-1 —— 破壞原始數據,語義不清。ArrayList<Integer>,猜中即 remove(guess) —— 結構自動緊湊,邏輯最清晰。import java.util.ArrayList;
public class SimpleDotCom {
private ArrayList<String> localCells; // 泛型指定元素類型
public void setDotCom(ArrayList<String> cells) {
this.localCells = cells;
}
public String checkYourself(String guess) {
String result = "miss";
if (localCells.contains(guess)) { // O(n) 查找
result = "hit";
localCells.remove(guess); // 猜中即移除,防止重複計分
}
if (localCells.isEmpty()) { // 列表為空 = 全部擊沉
result = "kill";
}
return result;
}
}
關鍵點:
ArrayList 不能直接存基本類型,需用包裝類(Integer、String 等),JDK 5+ 支援自動裝箱/拆箱。contains() + remove() 組合替代了手寫循環查找與標記。isEmpty() 直接判斷勝負,無需額外計數器。List<Integer> list = new ArrayList<>();
list.add(1);
list.add(null); // 允許加入 null
for (int i : list) { // 隱式拆箱調用 Integer.intValue()
sum += i; // 拆箱 null → NullPointerException
}
修正: 显式判空 sum += (i != null ? i : 0); 或改用 Integer 變量接收後再判斷。
equals() / compareTo()(建議 27)Integer a = 100, b = 100; // 自動裝箱走 IntegerCache
System.out.println(a == b); // true (-128~127 緩存區)
Integer c = 200, d = 200;
System.out.println(c == d); // false (新對象,地址不同)
結論: 任何包裝類比較大小或相等,一律用 equals() 或 compareTo(),切勿依賴 ==。
valueOf() 享受整型緩存(建議 28)Integer.valueOf(127) 返回緩存對象;new Integer(127) 每次新建。優先用 valueOf() 或直接賦值觸發自動裝箱,兼顧效能與記憶體。
方法重載解析規則:int → long → Long,但 int ↛ Long。混用基本/包裝類極易導致調用非預期重載,甚至發生無謂裝箱拆箱開銷。能用基本類型絕不用包裝類。
Random r = new Random(1000); // 固定種子 → 固定序列
for (int i=0; i<4; i++) System.out.println(r.nextInt());
// 每次運行輸出完全相同,失去隨機性
無參構造 new Random() 以 System.nanoTime() 為種子,天然不可預測。除非需復現特定測試場景,否則絕不手動設種子。
&& / || 具短路特性,& / | 不短路且常用於位運算,切勿混淆。