public class ObjectFactory { public static Object getInstance(String clsName) { try { // 建立指定類對應的Class物件 Class cls = Class.forName(clsName); // 返回使用該Class物件建立的範例 return cls.newInstance(); } catch (Exception e) { e.printStackTrace(); return null; } } }上面程式中第 5 、7 行程式碼根據指定的字串型別建立了一個新物件,但這個物件的型別是 Object,因此當需要使用 ObjectFactory 的 getInstance() 方法來建立物件時,程式碼如下:
// 獲取範例後需要強制型別轉換
Date d = (Date)ObjectFactory.getInstance("java.util.Date");
JFrame f = (JFrame)ObjectFactory .getInstance("java.util.Date");
上面程式碼在編譯時不會有任何問題,但執行時將丟擲 ClassCastException(強制型別轉換異常),因為程式試圖將一個 Date 物件轉換成 JFrame 物件。public class ObjectFactory2 { public static <T> T getInstance(Class<T> cls) { try { return cls.newInstance(); } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { // 獲取範例後無須型別轉換 Date d = CrazyitObjectFactory2.getInstance(Date.class); JFrame f = CrazyitObjectFactory2.getInstance(JFrame.class); } }在上面程式的 getInstance() 方法中傳入一個 Class<T> 引數,這是一個泛型化的 Class 物件,呼叫該 Class 物件的 newInstance() 方法將返回一個 T 物件,如程式中第 4 行程式碼所示。接下來當使用 ObjectFactory2 工廠類的 getInstance() 方法來產生物件時,無須使用強制型別轉換,系統會執行更嚴格的檢查,不會出現 ClassCastException 執行時異常。
// 使用Array的newInstance方法來建立一個陣列
Object arr = Array.newInstance(String.class, 10);
public static Object newInstance(Class<?> componentType, int... dimensions)
在這個方法簽名中使用了 Class<?> 泛型,但並沒有真正利用這個泛型。如果將該方法簽名改為如下形式:public static <T> T[] newInstance(Class<T> componentType, int length)
這樣就可以在呼叫該方法後無需強制型別轉換了。不過,這個方法暫時只能建立一維陣列,也就是不能利用可變個數的引數優勢了。public class CrazyitArray { // 對Array的newInstance方法進行包裝 @SuppressWarnings("unchecked") public static <T> T[] newInstance(Class<T> componentType, int length) { return (T[]) Array.newInstance(componentType, length); } public static void main(String[] args) { // 使用 CrazyitArray 的 newInstance()建立一維陣列 String[] arr = CrazyitArray.newInstance(String.class, 10); // 使用 CrazyitArray 的 newInstance()建立二維陣列 // 在這種情況下,只要設定陣列元素的型別是int[]即可 int[][] intArr = CrazyitArray.newInstance(int[].class, 5); arr[5] = "C語言中文網Java教學"; // intArr是二維陣列,初始化該陣列的第二個陣列元素 // 二維陣列的元素必須是一維陣列 intArr[1] = new int[]{ 23, 12 }; System.out.println(arr[5]); System.out.println(intArr[1][1]); } }上面程式中第 4、5、6、10 和 13 定義的 newInstance() 方法對 Array 類提供的 newInstance() 方法進行了包裝,將方法簽名改成了
public static <T> T[] newInstance(Class<T> componentType, int length)
,這就保證程式通過該 newInstance() 方法建立陣列時的返回值就是陣列物件,而不是 Object 物件,從而避免了強制型別轉換。
// 獲取成員變數 f 的型別
Class<?> a = f.getType();
// 獲得成員變數f的泛型型別
Type gType = f.getGenericType();
public class GenericTest { private Map<String, Integer> score; public static void main(String[] args) throws Exception { Class<GenericTest> clazz = GenericTest.class; Field f = clazz.getDeclaredField("score"); // 直接使用getType()取出型別只對普通型別的成員變數有效 Class<?> a = f.getType(); // 下面將看到僅輸出java.util.Map System.out.println("score 的型別是:" + a); // 獲得成員變數f的泛型型別 Type gType = f.getGenericType(); // 如果 gType 型別是 ParameterizedType物件 if (gType instanceof ParameterizedType) { // 強制型別轉換 ParameterizedType pType = (ParameterizedType) gType; // 獲取原始型別 Type rType = pType.getRawType(); System.out.println("原始型別是:" + rType); // 取得泛型型別的泛型引數 Type[] tArgs = pType.getActualTypeArguments(); System.out.println("泛型資訊是:"); for (int i = 0; i < tArgs.length; i++) { System.out.println("第" + i + "個泛型型別是:" + tArgs[i]); } } else { System.out.println("獲取泛型型別出錯!"); } } }上面程式中的第 12、16、18 和 21 行程式碼就是取得泛型型別的關鍵程式碼。執行上面程式,將看到如下執行結果:
score 的型別是:interface java.util.Map
原始型別是:interface java.util.Map
泛型資訊是:
第0個泛型型別是:class java.lang.String
第1個泛型型別是:class java.lang.Integer