Posted on 2012-06-12 16:26
陜西BOY 閱讀(223)
評論(0) 編輯 收藏 所屬分類:
java基礎知識點
Class反射對象描述類語義結構,可以從Class對象中獲取構造函數、成員變量、方法類等類元素的反射對象,并以編程的方式通過這些反射對象對目標類對象進行操作。這些反射對象類在java.reflect包中定義,下面是最主要的三個反射類:
- ? Constructor:類的構造函數反射類,通過Class#getConstructors()方法可以獲得類的所有構造函數反射對象數組。在JDK5.0中,還可以通過getConstructor(Class... parameterTypes)獲取擁有特定入參的構造函數反射對象。Constructor的一個主要方法是newInstance(Object[] initargs),通過該方法可以創建一個對象類的實例,相當于new關鍵字。在JDK5.0中該方法演化為更為靈活的形式:newInstance (Object... initargs)。
- ? Method:類方法的反射類,通過Class#getDeclaredMethods()方法可以獲取類的所有方法反射類對象數組Method[]。在JDK5.0中可以通過getDeclaredMethod(String name, Class... parameterTypes)獲取特定簽名的方法,name為方法名;Class...為方法入參類型列表。Method最主要的方法是invoke(Object obj, Object[] args),obj表示操作的目標對象;args為方法入參,代碼清單3 10③處演示了這個反射類的使用方法。在JDK 5.0中,該方法的形式調整為invoke(Object obj, Object... args)。此外,Method還有很多用于獲取類方法更多信息的方法: 1)Class getReturnType():獲取方法的返回值類型;
2)Class[] getParameterTypes():獲取方法的入參類型數組;
3)Class[] getExceptionTypes():獲取方法的異常類型數組;
4)Annotation[][] getParameterAnnotations():獲取方法的注解信息,JDK 5.0中的新方法; - ? Field:類的成員變量的反射類,通過Class#getDeclaredFields()方法可以獲取類的成員變量反射對象數組,通過Class#getDeclaredField(String name)則可獲取某個特定名稱的成員變量反射對象。Field類最主要的方法是set(Object obj, Object value),obj表示操作的目標對象,通過value為目標對象的成員變量設置值。如果成員變量為基礎類型,用戶可以使用Field類中提供的帶類型名的值設置方法,如setBoolean(Object obj, boolean value)、setInt(Object obj, int value)等。
此外,Java還為包提供了Package反射類,在JDK 5.0中還為注解提供了AnnotatedElement反射類。總之,Java的反射體系保證了可以通過程序化的方式訪問目標類中所有的元素,對于private或protected的成員變量和方法,只要JVM的安全機制允許,也可以通過反射進行調用,請看下面的例子:
代碼清單3-12 PrivateCarReflect
package com.baobaotao.reflect;
public class PrivateCar {
//①private成員變量:使用傳統的類實例調用方式,只能在本類中訪問
private String color;
//②protected方法:使用傳統的類實例調用方式,只能在子類和本包中訪問
protected void drive(){
System.out.println("drive private car! the color is:"+color);
}
}
color變量和drive()方法都是私有的,通過類實例變量無法在外部訪問私有變量、調用私有方法的,但通過反射機制卻可以繞過這個限制:
public class PrivateCarReflect {
public static void main(String[] args) throws Throwable{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass("com.baobaotao.reflect.PrivateCar");
PrivateCar pcar = (PrivateCar)clazz.newInstance();
Field colorFld = clazz.getDeclaredField("color");
//①取消Java語言訪問檢查以訪問private變量
colorFld.setAccessible(true);
colorFld.set(pcar,"紅色");
Method driveMtd = clazz.getDeclaredMethod("drive",(Class[])null);
//Method driveMtd = clazz.getDeclaredMethod("drive"); JDK5.0下使用
//②取消Java語言訪問檢查以訪問protected方法
driveMtd.setAccessible(true);
driveMtd.invoke(pcar,(Object[])null);
}
}
運行該類,打印出以下信息:
引用
drive private car! the color is:紅色
在訪問private、protected成員變量和方法時必須通過setAccessible(boolean access)方法取消Java語言檢查,否則將拋出IllegalAccessException。如果JVM的安全管理器設置了相應的安全機制,調用該方法將拋出SecurityException。