如果不知道一個類的確切類型,RTTI(運行時類型信息)可以告訴我們。但是,這個類必須在編譯時是已知的。這樣無形給編程增加了一個限制,如果有下面的情況:假設你要獲取一個並不在你的程序空間的對象的引用,例如:從硬盤或者網絡上獲取一個字符串,並且這些字符串是一個個的類名稱。這個類在編譯器編譯後很久纔會出現,那麼怎麼才能使用這些類!這樣就產生程序了運行時,獲取類信息的需求。運行時獲取類信息的類的動態加載可以提供跨網絡的遠程平臺上創建和運行對象的能力。
JAVA的反射機制是一直允許程序運行時動態加載和使用類的機制,每一個load到內存的class都是一個個的對象。近距離方法這些對象,它們有方法和屬性;每一個方法、屬性又都是對象。
Class類和java.lang.reflect類庫一起實現了反射的概念。java.lang.reflect類庫包含Field,Method和Constructor類,這些類都是JVM運行時創建的,用來表示未知類裏面的成員。這樣就可以用Constructor創建新對象,用get()和set()讀取和修改與Field對象關聯的字段,用invoke ()調用與Method對象關聯的方法。
程序實例:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.sun.java.util.*;
public class TestReflection {
/**
* @param args
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
* @throws ClassNotFoundException
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
String str = "T";
//T t = new T(); //此方法不夠靈活!
Class c = Class.forName(str); //名字叫String 的類裝載到內存;
Object o = c.newInstance(); //new 一個T的對象;拋非法訪問的對象
Method[] methods = c.getMethods();
for(Method m : methods){
System.out.println(m.getName());
if(m.getName().equals("mm")){
m.invoke(o);
}
}
}
}
class T {
int i ;
String s;
static {
System.out.println("T loaded");
}
public T() {
System.out.println("T constructed!");
}
public void m1(int i){
this .i = i;
}
public String gets(){
return s;
}
public void mm() {
System.out.println("mm invock");
}
}