Java反射中的Array類,java.lang.reflect包下的Array類

 

今天我們聊一聊java.lang.reflect包下的Array類,重點關注其中的newInstance方法。

1、Array類的簡單使用

java.lang.reflect包下除了提供Method(方法)、Constructor(構造器)、Filed(成員變量)這三個類,還提供了Array類,Array對象可以代表所有的數組,可通過Array類來動態創建數組,該類提供了以下類方法:

  • static Object newInstance(Class<?> componentType, int... dimensions):創建指定元素類型、指定維度的數組。這裏的dimensions是可變個數的。
  • static xxx getXxx(Object arr, int index):返回arr數組的第index位置元素。這裏xxx表示基本數據類型,比如getChar,getInt;若數組元素是引用類型,該方法變爲get((Object arr, int index)
  • static void setXxx((Object arr, int index, xxx val):向arr數組的第index位置插入val值

對於上述方法,下面有個非常簡單的例子:

public class ReflectArrayTest {
    public static void main(String args[]) {
        try {
            // 創建長度爲5,元素類型爲String的數組
            Object arr = Array.newInstance(String.class, 5);

            Array.set(arr, 3, "ttt");
            Array.set(arr, 4, "fff");
            Object obj = Array.get(arr, 3);
            Object obj1 = Array.get(arr, 4);
        } catch (Throwable e) {
            System.err.println(e);
        }
    }
}

上述例子只是創建了簡單的一維數組,利用Array.newInstance還可以創建多維數組。

 

2、newInstance()方法返回值並不是泛型

在上述例子雖然創建String數組,但是其返回值只是簡單的Object對象,如果需要將arr對象當成String[]數組來用,就必須使用強轉:String[] cast = (String []) arr;,但是強轉是不安全的操作。而在反射中使用泛型Class<T>,可以有效避免強制類型轉化。

觀察Array的newInstance的方法簽名,可以觀察到奇怪的一點:

public static Object newInstance(Class<?> componentType, int... dimensions)

雖然方法簽名中使用了Class<?>泛型,但實際上並沒有真正利用泛型。如果將方法返回值改成如下形式:

public static <T> T[] newInstance(Class<T> componentType, int... dimensions)  這樣就可以在調用該方法後無需強制類型轉化了。不過改動了的這個方法只能暫時創建一維數組,就不能利用可變個數的參數優勢了。

我們可以將Array的newInstance方法封裝一下:

public class PackageArray {
    // 強轉的時候,會有一個unchecked編譯警告,使用該註解可以抑制這個警告信息
    @SuppressWarnings("unchecked")
    public static <T> T[] newInstance(Class<T> componentType, int length) {
        return (T[])Array.newInstance(componentType, length);
    }
}

封裝後,調用PackageArray的newInstance類方法,就可直接獲取到具體元素類型的數組對象了。

 

發佈了48 篇原創文章 · 獲贊 35 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章