首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 反射動態建立指定型別陣列:Array.newInstance 避免 Object[] 強轉失敗

     編輯:程式設計疑難解答

工具方法 `getArray(Class c, String sql)` 需根據傳入的 `Class` 物件動態建立對應型別陣列(如 `String[]`、`User[]`)。直接 `list.toArray(new Object[size])` 回傳 `Object[]`,**無法強轉為 `String[]` 或具體型別陣列**(會拋 `ClassCastException`)。正解是用 `java.lang.reflect.Array.newInstance`。

錯誤示範

public static Object[] getArray(Class c, String str) {
    List list = jdbcUtil.getList(c, str);  // List<具体Bean>
    return list.toArray(new Object[list.size()]);  // 回傳 Object[]
}

// 呼叫端
String[] arr = (String[]) getArray(String.class, "sql");  // ❌ ClassCastException

正確實作:Array.newInstance

import java.lang.reflect.Array;
import java.util.List;

public static  T[] getArray(Class clazz, String sql) {
    List list = jdbcUtil.getList(clazz, sql);  // 假設已泛型化
    // 關鍵:建立 T[] 型別陣列
    @SuppressWarnings("unchecked")
    T[] array = (T[]) Array.newInstance(clazz, list.size());
    return list.toArray(array);  // 直接填充到指定型別陣列
}

// 使用
String[] strs = getArray(String.class, "SELECT name FROM users");
User[] users = getArray(User.class, "SELECT * FROM users");

核心 API 對照

方法用途範例
`Array.newInstance(Class componentType, int length)`建立一維指定型別陣列`String[] arr = (String[]) Array.newInstance(String.class, 10);`
`Array.newInstance(Class componentType, int... dimensions)`建立多維陣列`int[][] matrix = (int[][]) Array.newInstance(int.class, 3, 4);`
`Array.get(Object array, int index)`讀取陣列元素`Object val = Array.get(arr, 0);`
`Array.set(Object array, int index, Object value)`設定陣列元素`Array.set(arr, 0, "hello");`
`Array.getLength(Object array)`取得陣列長度`int len = Array.getLength(arr);`

完整工具類(含泛型輔助、空值防護)

public final class ArrayUtils {
    private ArrayUtils() {}

    @SuppressWarnings("unchecked")
    public static  T[] toArray(List list, Class clazz) {
        if (list == null) return null;
        T[] array = (T[]) Array.newInstance(clazz, list.size());
        return list.toArray(array);
    }

    // 當只有 Class 物件、無泛型資訊時
    public static Object newArray(Class componentType, int length) {
        return Array.newInstance(componentType, length);
    }

    // 複製陣列並改變型別(如 Object[] → String[])
    @SuppressWarnings("unchecked")
    public static  T[] copyOf(Object[] src, Class clazz) {
        if (src == null) return null;
        T[] dest = (T[]) Array.newInstance(clazz, src.length);
        System.arraycopy(src, 0, dest, 0, src.length);
        return dest;
    }
}

為什麼 `Object[]` 無法強轉 `String[]`?

  • Java 陣列是**共變**的:`String[]` 是 `Object[]` 的子型別,**但 `Object[]` 不是 `String[]` 的父型別**
  • `new Object[10]` 在堆上建立的物件**運行時型別就是 `Object[]`**,JVM 拒絕視為 `String[]`
  • `Array.newInstance(String.class, 10)` 建立的物件**運行時型別真正是 `String[]`**,可安全強轉

JDBC 工具配合建議

// jdbcUtil.getList 簽名建議泛型化
public  List getList(Class clazz, String sql, Object... params) {
    // 內部用 BeanPropertyRowMapper / ResultSetMapper 映射
    return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(clazz), params);
}

掌握 `Array.newInstance(componentType, length)` 動態建立具體型別陣列,配合 `list.toArray(typedArray)`,即可完美解決反射場景下的陣列型別轉換問題。

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