List list = new ArrayList<>();
list.add("Hello");
list.add("World");
// 錯誤寫法:編譯通過,運行拋 ClassCastException
String[] arr = (String[]) list.toArray();
// 正確寫法
String[] arr2 = list.toArray(new String[0]); // 或 new String[list.size()]
List.toArray() 簽名與實現// List 接口
Object[] toArray(); // 無參版本
T[] toArray(T[] a); // 有參版本 (泛型)
// ArrayList 實現 (簡化)
public Object[] toArray() {
return Arrays.copyOf(elementData, size); // 返回 Object[]!
}
public T[] toArray(T[] a) {
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size) a[size] = null;
return a;
}
List 運行時只是 List,元素類型為 Object。toArray() 無參版本只能返回 Object[],因為編譯器不知道具體元素類型。String[] 運行時類型就是 String[],Object[] 無法強轉為 String[] (雖然 String 是 Object 子類,但數組協變導致 String[] 是 Object[] 子類,反向轉換需檢查)。(String[]) list.toArray() 會拋異常?Object[] objArr = list.toArray(); // 實際類型 Object[]
String[] strArr = (String[]) objArr; // 執行時類型檢查失敗:Object[] cannot be cast to String[]
JVM 運行時檢測到 objArr 真實類型是 Object[],而非 String[],拋出 ClassCastException。
| 寫法 | 結果 | 性能 | 推薦度 |
|---|---|---|---|
| ✅ 正確 | JVM 逃逸分析優化,無額外分配 | ⭐⭐⭐⭐⭐ (Java 8+ 推薦) | |
| ✅ 正確 | 精確分配,避免擴容拷貝 | ⭐⭐⭐⭐ (大列表微優) | |
| ❌ ClassCastException | -- | 🚫 禁用 | |
| ✅ 返回 Object[] | -- | ⚠️ 需後續手動轉換 |
// 關鍵:a.getClass() 獲取運行時數組組件類型
(T[]) Arrays.copyOf(elementData, size, a.getClass());
傳入 new String[0] 時,a.getClass() 返回 String[].class,Arrays.copyOf 以此創建 正確類型的新數組,最後安全返回 T[] (即 String[])。
Map map = new HashMap<>();
map.put("a", 1);
// Key 陣列
String[] keys = map.keySet().toArray(new String[0]);
// Value 陣列 (注意:值類型需一致)
Integer[] values = map.values().toArray(new Integer[0]);
// Entry 陣列
Map.Entry[] entries = map.entrySet().toArray(new Map.Entry[0]);
list.toArray(new T[0]) (Java 6+) 或 list.toArray(new T[list.size()])。toArray():僅當你確定只需 Object[] 時使用。(SomeType[]) collection.toArray() 模式。List.toArray() 無參版本因泛型擦除只能返回 Object[],強轉為具體類型數組必失敗。正解是調用有參版本 toArray(new String[0]),利用傳入數組的運行時類型資訊創建正確類型數組。這是 Java 集合轉數組的「鐵律」,請寫入團隊編碼規約並配置靜態檢查規則 (SpotBugs/Error Prone) 自動攔截。