java反射—— 對類的分析

lengtianxue發表於2016-09-14

轉自http://uuhorse.iteye.com/blog/1706466


反射API使得Java語言更易實現執行時的動態性,獲取Java程式在執行時刻的內部結構,如Java列中的構造方法、域和方法等。反射API的主要功能包括:

    ① 確定一個物件的類
    ② 取出類的修飾符(modifiers),欄位,方法,構造器和超類
    ③ 找出某個介面裡定義的常量和方法說明
    ④ 建立一個類例項,這個例項在執行時刻才有名字(執行時間才生成的物件)
    ⑤ 取得和設定物件資料成員的值,如果資料成員名是執行時刻確定的也能做倒。
    ⑥ 在執行時刻呼叫動態物件的方法

    ⑦ 建立陣列,陣列大小和型別在執行時刻才確定。也能更改陣列成員的值。  



① 獲取物件的類(Class物件)

Class c = obj.getClass(); 
② 獲取一個類的超類

Class sc = c.getSuperclass(); 
③ 獲取類的名字

Class c = obj.getClass(); 
String name = c.getName(); 

④ 獲取類的修飾符 

Class c = obj.getClass(); 
int m = c.getModifiers(); 

此處getModifiers()方法返回的是個整型的結果,結果m並不具體表示哪一種修飾符。先看java.lang.reflect.Modifier類,該類對修飾符進行了相應的包裝。
    類Modifier中定義了一系列的類描述符常量:Modifier.ABSTRACT、Modifier.FINAL、Modifier.PUBLIC等。getModifiers()方法返回的即是類的所有修飾符分別對應的整型值的或運算結果。

如public abstract class MyClass{},new MyClass().getClass().getModfiers()即得到Modifier.ABSTRACT | Modifier.PUBLIC。
    同時Modifier類提供了一些列的方法,用於判斷getModifiers()返回的整型數字中包含的類修飾符:Modifier.isPublic(m)、Modifier.isAbstract(m)、Modifier.isFinal(m)等。

public class Point {
	private int x;  
	private int y;  
      
	private  String s1 ="ball";  
	private String s2="hubin";  
	private String s3="zhangxiaoxiang";  
    
    public Point(int x, int y) {  
        super();  
        this.x = x;  
        this.y = y; 

}
}


 

	// 分析類的修飾符  
	public static void printModifiers(Object obj) {  
	    System.out.print("Modifier: \n");   
	    Class c = obj.getClass();  
	    int m = c.getModifiers();  
	    if (Modifier.isPublic(m))  
	        System.out.print("public \n");  
	    if (Modifier.isAbstract(m))  
	        System.out.print("abstract \n");  
	    if (Modifier.isFinal(m))  
	        System.out.print("final \n");  
	    System.out.println(c.getName());  
	} 
public static void main(String[] args) throws Exception {
	
		Point pt1 = new Point(3, 5);
		printModifiers(pt1);

		

	}

輸出結果:

Modifier: 
public 
reflect.Point

⑤ 確定一個類實現的介面
    Class[] theInterfaces = c.getInterfaces();
    從上面的語句中可以看到,介面在反射的API中也是用Class表示的,介面是一種特殊的抽象類。可以使用Class類的isInterface()方法判斷一個Class型別是一個類還是介面。

    // 分析類的介面  
    public static void printInterfaceNames(Object o) {  
        Class c = o.getClass();  
        Class[] theInterfaces = c.getInterfaces();  
        for (int i = 0; i < theInterfaces.length; i++) {  
            String interfaceName = theInterfaces[i].getName();  
            System.out.println(interfaceName);  
        }  
    }  
    // 判斷介面  
    public static void verifyInterface(Class c) {  
        String name = c.getName();  
        if (c.isInterface()) {  
            System.out.println(name + "  是介面.");  
        } else {  
            System.out.println(name + "  是類.");  
        }  
    }  

⑥ 獲取類的欄位
    一個類的欄位(Field)可能來自本類、父類、實現的介面或者介面的介面,可以使用Class物件的getFields()方法獲取類中所有的public屬性的欄位的陣列(Field物件陣列)。Field物件提供方法取得欄位的名字、型別和描述符,甚至可以給欄位賦值或者取欄位的值。當然,Class類物件提供了getDeclaredFields()方法獲取包括public屬性在內的所有在類中宣告瞭的域。 

// 分析類的欄位  
public static void printFieldNames(Object o) {  
    Class c = o.getClass();  
    //public的欄位  
    Field[] publicFields = c.getFields();  
    for (int i = 0; i < publicFields.length; i++) {  
        String fieldName = publicFields[i].getName();  
        Class typeClass = publicFields[i].getType();  
        String fieldType = typeClass.getName();  
        System.out.println("欄位名: " + fieldName + ",  型別: " + fieldType);  
    }  
    //所有的欄位  
    Field[] allFields = c.getDeclaredFields();  
    for (int i = 0; i < allFields.length; i++) {  
        String fieldName = allFields[i].getName();  
        Class typeClass = allFields[i].getType();  
        String fieldType = typeClass.getName();  
        System.out.println("欄位名: " + fieldName + ",  型別: " + fieldType);  
    }  
} 

⑦ 獲取構造方法
    構造方法是在建立類物件時呼叫的特殊方法,構造方法可以過載,由它們的引數加以區別。呼叫getConstructors方法可以取得類構造方法的有關資訊,這個方法返回一個陣列的
Constructor物件。可以用 Constructor物件裡的相關方法來確定構造方法的名字、描述符、引數型別和丟擲的意外列表。也可以用Constructor.newInstance建立一個新的Constructor物件。 


    //分析類的構造方法  
    public static void showConstructors(Object o) {  
        Class c = o.getClass();  
        Constructor[] theConstructors = c.getConstructors();  
        for (int i = 0; i < theConstructors.length; i++) {  
            System.out.print(theConstructors[i].getName());  
            System.out.print(" ( ");  
            Class[] parameterTypes = theConstructors[i].getParameterTypes();  
            for (int k = 0; k < parameterTypes.length; k++) {  
                String parameterString = parameterTypes[k].getName();  
                System.out.print(parameterString + " ");  
            }  
            System.out.println(")");  
        }  
    }  

⑧ 獲取成員方法
    如何找出類的public方法呢?當然是呼叫getMethods方法。由getMethods方法返回一個陣列,陣列元素型別是Method物件。方法的名字,型別,引數,描述和丟擲的意外都可
以由Method物件的方法來取得。用 Method.invoke 方法自己呼叫這個方法。
    Method類的物件可以通過getName取方法名、getReturnType取返回值的型別、用
getParameterTypes取得引數型別(Class物件)的陣列,對每個引數用getName取引數的型別名。
    同樣,對於非public的方法,可以使用getDeclaredMethods()方法獲取。 
    //分析類中的成員方法  
    public static void showMethods(Object o) {  
        Class c = o.getClass();  
        Method[] theMethods = c.getMethods();  
        for (int i = 0; i < theMethods.length; i++) {  
            String methodString = theMethods[i].getName();  
            System.out.println("Name: " + methodString);  
            String returnString = theMethods[i].getReturnType().getName();  
            System.out.println("   Return Type: " + returnString);  
            Class[] parameterTypes = theMethods[i].getParameterTypes();  
            System.out.print("   Parameter Types:");  
            for (int k = 0; k < parameterTypes.length; k++) {  
                String parameterString = parameterTypes[k].getName();  
                System.out.print(" " + parameterString);  
            }  
            System.out.println();  
        }  
    }  



相關文章