動態生成物件


你可以使用反射動態載入.class,從中擷取類別資訊,你也可以直接利用載入的.class之Class實例,動態生成物件。

您可以使用Class的newInstance()方法來實例化一個物件,例如: 
Class c = Class.forName(args[0]);
Object obj = c.newInstance();

如果載入的類別定義有無參數的建構函式,則可以使用這種方式來建構一個不指定初始參數的物件,如果要在動態載入及生成物件時指定參數,則要先指定參數類別、取得Constructor物件、使用Constructor的newInstance()並指定參數值。

以一個例子來說明,首先定義一個Student類:
package cc.openhome;

public class Student {

    private String name;
    private int score;
   
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public int getScore() {
        return score;
    }
   
    public String toString() {
        return "Student [name=" + name + ", score=" + score + "]";
    }
}

然後以動態載入的方式來動態生成物件:
Class clz = Class.forName("cc.openhome.Student");
// 指定參數型態
Class[] params = {String.class, Integer.TYPE};
Constructor constructor = clz.getConstructor(params);
// 指定參數內容
Object[] paramObjs = {"caterpillar", new Integer(90)};
// 實例化
Object obj = constructor.newInstance(paramObjs);
System.out.println(obj);

上面的例子會顯示Student [name=caterpillar, score=90]。

如果要生成陣列的話,該怎麼作?陣列的類別是由JVM生成,陣列每個索引位置會有其型態,而且陣列還有維度資訊,如果要動態生 成陣列,則必須使用java.lang.reflect.Array的newInstance()方法。例如以下動態生成長度為10的Student陣 列:
Class clz = Class.forName("cc.openhome.Student");
Student[] students = (Student[]) Array.newInstance(clz, 10);

這沒什麼實用性,只是說明動態生成陣列的方式而已,也許一個比較實際的例子,可以在 再來看看角括號 中看到,搭配泛型與動態陣列生成:
public class ArrayUtil {
    @SuppressWarnings(value={"unchecked"})
    public static <T> T[] toOneByColumn(T[][] array) {
        T[] arr = (T[]) Array.newInstance(
                           array[0].getClass().getComponentType(),
                           array.length * array[0].length);
        for(int row = 0; row < array.length; row++) {
            for(int column = 0; column < array[0].length; column++) {
                arr[row + column * array.length] = array[row][column];
            }
        }
        return arr;
    }
}

二維以上陣列的話,可以透過一個int陣列來宣告其維度,例如下面這個程式示範如何設定與取得二維陣列的值:
int[] dim = new int[]{3, 4};
Object arr = Array.newInstance(String.class, dim);
for(int i = 0; i < dim[0]; i++) {
    Object row = Array.get(arr, i);
    for(int j = 0; j < dim[1]; j++) {
        Array.set(row, j, "" + (i+1)*(j+1));
    }
}
       
for(int i = 0; i < dim[0]; i++) {
    Object row = Array.get(arr, i);
    for(int j = 0; j < dim[1]; j++) {
        System.out.print(Array.get(row, j) + " ");
    }
    System.out.println();
}