你可以使用反射動態載入.class,從中擷取類別資訊,你也可以直接利用載入的.class之Class實例,動態生成物件。
您可以使用Class的newInstance()方法來實例化一個物件,例如:
Class c = Class.forName(args[0]);
Object obj = c.newInstance();
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 + "]";
}
}
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);
// 指定參數型態
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);
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;
}
}
@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();
}
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();
}