在《Java 編程思想》第十章中,Bruce Eckel 指出:若程序僅處理固定數量、生命週期已知的對象,設計將極其簡單。但現實中,我們往往在運行時才能確定需要多少對象、甚至具體類型。為了解決「隨時隨地創建任意數量對象」的需求,Java 提供了數組與集合類(Collection Classes)兩大機制。本文將深入剖析兩者的異同、優劣,並通過大量代碼示例演示最佳實踐。
數組標識符本質是指向堆內存對象的引用。堆對象包含:
示例:多種初始化方式與引用傳遞
// 對象數組:自動初始化為 null
Weeble[] b = new Weeble[5]; // 5 個 null 引用
Weeble[] c = new Weeble[4];
for (int i = 0; i < c.length; i++) c[i] = new Weeble(); // 逐個實例化
Weeble[] d = { new Weeble(), new Weeble(), new Weeble() }; // 集合初始化
// 基本類型數組:自動初始化為 0/false/'\u0000'
int[] f = new int[5]; // {0,0,0,0,0}
int[] h = { 11, 47, 93 };
// 引用傳遞:a、d 指向同一堆對象
Weeble[] a = d;
a = new Weeble[] { new Weeble(), new Weeble() }; // Java 1.1 動態初始化語法
C/C++ 返回指針易發生內存洩漏;Java 返回數組引用,由 GC 自動管理生命週期:
static String[] flavorSet(int n) {
n = Math.abs(n) % (flav.length + 1);
String[] results = new String[n];
int[] picks = new int[n];
Arrays.fill(picks, -1);
for (int i = 0; i < picks.length; i++) {
retry: while (true) {
int t = (int) (Math.random() * flav.length);
for (int j = 0; j < i; j++)
if (picks[j] == t) continue retry;
picks[i] = t;
results[i] = flav[t];
break;
}
}
return results; // 僅返回引用,GC 會在無引用時回收
}
早期集合(Vector、Stack、Hashtable)存儲 `Object` 引用,導致:
Vector cats = new Vector();
for (int i = 0; i < 7; i++) cats.addElement(new Cat(i));
cats.addElement(new Dog(7)); // 編譯通過,運行崩潰
for (int i = 0; i < cats.size(); i++)
((Cat) cats.elementAt(i)).print(); // 第 7 次拋異常
class GopherVector {
private Vector v = new Vector();
public void addElement(Gopher m) { v.addElement(m); }
public Gopher elementAt(int index) { return (Gopher) v.elementAt(index); }
public int size() { return v.size(); }
}
// 使用:gophers.addElement(new Pigeon()); // 編譯報錯!
C++ `template`、Ada `generic` 早已解決此問題。Java 1.0/1.1 僅保留 `generic` 關鍵字未實現,直至 Java 5 引入泛型才徹底解決。(註:本文基於早期版本視角)
| 場景 | 推薦 | 理由 |
|---|---|---|
| 已知固定大小、高頻隨機訪問、基本類型 | 數組 | 零開銷、類型安全、緩存友好 |
| 動態增減、未知數量、對象存儲 | ArrayList / LinkedList | 自動擴容、豐富 API、泛型支持 |
| 鍵值映射、快速查找 | HashMap | O(1) 平均查找 |
| 線程安全舊代碼維護 | Vector / Hashtable | 同步方法,但性能差,新代碼用 ConcurrentHashMap |
數組是 Java 中「最高效、類型最安全」的容器,但缺乏彈性;早期集合犧牲類型安全換取通用性,需程序員自律或封裝器輔助。現代 Java 開發應優先使用泛型集合(`List