JAVA 反射機制是Java 被視為動態(或準動態)語言的一個關鍵性質。這個機制允許程式在運行時通過Reflection APIs 取得任何一個已知名稱的class 的內部資訊,包括其modifiers(諸如public, private,static 等等)、superclass(例如Object)、interfaces(例如Cloneable),也包括fields 和methods 的所有資訊, 並在運行時調用任意一個對象的方法;生成動態代理。下面以一段代碼來看一下主要的Reflection APIs,代碼中有相應的註釋。
Java代碼
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Goods
{
private String id;
private double price;
public Goods(){
System.out.println("it is a pen");
}
public Goods(String s1,String s2){
System.out.println(s1+"*"+s2);
}
public String getId()
{
System.out.println(id);
return id;
}
public void setId(String id)
{
this.id = id;
}
public String addName(String str1,String str2){
return str1+str2;
}
/**
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws NoSuchFieldException
* @功能描述
* @輸入參數
* @反饋值
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException
{
// TODO Auto-generated method stub
String str = "com.xtlh.sinye.Goods";
Class c = Class.forName(str);
Object obj = c.newInstance();//初始化一個Goods的對象
/**
* //這裡設置屬性的值 調用setId()方法,類型用Class[],參數用Object[]
*/
Method m = c.getMethod("setId",new Class[]{Class.forName("java.lang.String")});
m.invoke(obj,new Object[]{"it's apple"});
System.out.println("———————————————————————");
/**
* //這裡是裡獲取屬性的值 調用getId()方法
*/
m = c.getMethod("getId",new Class[]{});
m.invoke(obj,new Object []{});
System.out.println("———————————————————————");
/**
* //獲得類中聲明的方法
*/
Method me[] = c.getDeclaredMethods();
for(int i=0;i<me.length;i++){
System.out.println("method["+i+"]="+me[i].toString());
}
System.out.println("———————————————————————");
/**
* //模擬 instanceof 操作符
*/
boolean b1 = c.isInstance(new Integer(34));
System.out.println("Goods is a instance of Integer ? "+b1);
boolean b2 = c.isInstance(new Goods());//這裡調用瞭無參的構造方法
System.out.println("Goods is a instance of Goods ? "+b2);
System.out.println("———————————————————————");
/**
* //找出類的方法,類的名稱,類的方法的參數,類的方法的返回類型
*/
Method med[] = c.getDeclaredMethods();
Method med1[] = c.getMethods();//從字面意思可以看出來,這裡找到所有的方法,即可以找到繼承來的方法等
for(int i=0;i<med.length;i++){
Method mee = med[i];
System.out.println("method # "+i+" name="+mee.getName());
System.out.println("declaring class ="+mee.getDeclaringClass());
//方法的參數類型
Class pvec[] = m.getParameterTypes();
for(int j=0;j<pvec.length;j++){
System.out.println("parameter # "+j+" ="+pvec[j]);
}
//方法的異常
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++){
System.out.println("exception #" + j + " " + evec[j]);
}
//方法的返回類型
System.out.println("return type = " + mee.getReturnType());
}
System.out.println("———————————————————————");
/**
* //獲取類的構造函數
*/
Constructor ctorlist[] = c.getDeclaredConstructors();
for(int i=0;i<ctorlist.length;i++){
Constructor cons = ctorlist[i];
System.out.println("Constructor #"+i+" name="+cons.getName());
Class[] consParaType = cons.getParameterTypes();//獲得構造函數的參數類型
if(consParaType.length==0){
System.out.println("Constructor have no parameters");
}else{
for(int j=0;j<consParaType.length;j++){
System.out.println("Constructor Parameter type #"+j+" name="+consParaType[j]);
}
}
}
System.out.println("———————————————————————");
/**
* //獲取類的屬性
*/
Field fieldlist[] = c.getDeclaredFields();
for(int i=0;i<fieldlist.length;i++){
Field field = fieldlist[i];
System.out.println("Filed #"+i+" name="+field.getName());//屬性名稱
System.out.println("Filed #"+i+" type="+field.getType());//屬性類型
int mod = field.getModifiers();
System.out.println("modifiers = " + Modifier.toString(mod));//屬性的修飾符 private/public/protected
}
System.out.println("———————————————————————");
/**
* //根據方法的名稱來執行方法
*/
Class cls = Class.forName("com.xtlh.sinye.Goods");
Class partypes[] = new Class[2];
partypes[0] = String.class;//更多類型 Long.TYPE Integer.TYPE,或者使用Long.class、Integer.class
partypes[1] = Class.forName("java.lang.String");
Method meth = cls.getMethod("addName", partypes);
Goods goods = new Goods();
Object arglist[] = new Object[2];
arglist[0] = new String("love");
arglist[1] = new String("grape");
Object retobj = meth.invoke(goods, arglist);
String retval = (String) retobj;
System.out.println(retval);
System.out.println("———————————————————————");
/**
* 創建對象,根據指定的參數類型找到相應的構造函數並執行它,以創建一個新的對象實例。使用這種方法可以在程序運行時動態地創建對象,而不是在編譯的時候創建對象,這一點非常有價值
*/
Class clss = Class.forName("com.xtlh.sinye.Goods");
Class partypess[] = new Class[2];
partypess[0] = String.class;
partypess[1] = String.class;
Constructor ct = clss.getConstructor(partypess);
Object arglists[] = new Object[2];
arglists[0] = new String("hello");
arglists[1] = new String("orange");
Object retobjs = ct.newInstance(arglists);
System.out.println("———————————————————————");
/**
* //改變屬性的值
*/
Class ccc = Class.forName("com.xtlh.sinye.Goods");
Field fld = ccc.getDeclaredField("price");
Goods goods1 = new Goods();
System.out.println("price = " + goods1.price);
fld.setDouble(goods1, 25.0);
System.out.println("price = " + goods1.price);
System.out.println("———————————————————————");
/**
* //簡單使用數組,創建瞭 10 個單位長度的 String 數組,為第 5 個位置的字符串賦瞭值,最後將這個字符串從數組中取得並打印瞭出來
*/
Class cla = Class.forName("java.lang.String");
Object arr = Array.newInstance(cla, 10);
Array.set(arr, 5, "hello Watermelon");
String s = (String) Array.get(arr, 5);
System.out.println(s);
System.out.println("———————————————————————");
/**
* //復雜數組使用,例中創建瞭一個 5 x 10 x 15 的整型數組,並為處於 [3][5][10] 的元素賦瞭值為 37。註意,多維數組實際上就是數組的數組,例如,第一個 Array.get 之後,arrobj 是一個 10 x 15 的數組。進而取得其中的一個元素,即長度為 15 的數組,並使用 Array.setInt 為它的第 10 個元素賦值。
註意創建數組時的類型是動態的,在編譯時並不知道其類型。
*/
int dims[] = new int[]{5, 10, 15};
Object array = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(array, 3);
Class cl = arrobj.getClass().getComponentType();
System.out.println(cl);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][]) array;
System.out.println(arrcast[3][5][10]);
}
}
作者“xSTARx”