1. 程式人生 > >利用 反射 檢查類的結構 Class類和java.lang.reflect包的使用 ( 含demo )

利用 反射 檢查類的結構 Class類和java.lang.reflect包的使用 ( 含demo )

先上執行效果:  輸入我們想分析檢查的類(全類名, 帶包名), 以java.lang.Double為例

可以看到Double類的結構一覽無餘,無論公有私有 是否為final和static, 即使native的本地方法都被我們的火眼金睛發現了, 這就是java反射機制的威力, 其實更可怕的是反射不僅僅用於編譯程式時可以使用的類, 更多的是在程式執行的時候動態地分析類的結構並建立例項, 再通過代理機制與之配合,  (這也就是java框架的核心機制) 所以java.lang.reflect包是開發人員的利器啊!

 

看到效果了, 那我們的反射到底怎麼用呢? java.lang.reflect包

又有啥工具呢?

 

java.lang.reflect包中有三個類Field, Method, Contructor分別用於描述類的域, 方法和構造器

Field類中有一個getType方法,用來返回描述域所屬型別的Class物件

Method 和 Contructor 類有能夠報告引數型別的方法,Method類還有一個可以報告返回型別的方法

三個類都有一個叫做getModifiers的方法, 它將返回一個整形數值, 用不同的位開關描述public和static 這樣的描述符的使用情況

另外,還可以利用java.lang.reflect包中的Modifier類

的靜態方法分析getModifiers()返回的整形數值。

例如,可以使用Modifier類中的isPublic 、isPrivate 、或isFinal判斷方法或者構造器是否是public、private或者final。

我們需要做的全部工作就是呼叫Modifier類中的相應方法,並對返回的整型數值進行分析,另外,還可以利用Modifier.toString 方法 將修飾符打印出來。

Class類中的getFields,getMethods和getContructors 方法將分別返回類提供的public域,方法,和構造器陣列,其中包括超類公有成員

Class類的getDeclareFields、getDeclareMethods和getDeclareContructors

方法將分別返回類中宣告的全部域、方法和構造器,其中包括私有的和受保護的成員,但不包括超類的成員

 

我們的demo原始碼:

package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;

public class ReflectionTest {

	public static void main(String[] args) {
		String name;
		if(args.length>0) name=args[0];
		else {
			Scanner in=new Scanner(System.in);
			System.out.println("Enter class name (e.g. java.util.Date):");
			name=in.next();
			
		}
		try {
			Class cl=Class.forName(name);
			Class supercl=cl.getSuperclass();
			String modifiers=Modifier.toString(cl.getModifiers());
			if(modifiers.length()>0)System.out.print(modifiers+"");
			System.out.print("class "+name);
			if(supercl!=null&&supercl!=Object.class)System.out.print(" extends"+supercl.getName());
			System.out.println("\n{\n");
			printConstructors(cl);
			System.out.println();
			printMethods(cl);
			System.out.println();
			printFields(cl);
			System.out.println("}");
		}
		catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		System.exit(0);
	}

	
	
	
	public static void printConstructors(Class cl){
		Constructor[] constructors=cl.getDeclaredConstructors();
		//Declared
		for(Constructor c:constructors)
		{
			String name=c.getName();
			System.out.print("	");
			String modifiers=Modifier.toString(c.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers+" ");
			System.out.print(name+"(");
			Class[] paramTypes=c.getParameterTypes();
			for(int j=0;j<paramTypes.length;j++)
			{
				if(j>0)
					System.out.print(",");
				System.out.print(paramTypes[j].getName());
			}	
			System.out.println(");");
		}
		
	}
	
	public static void printMethods(Class cl) 
	{
		//Method[] methods= cl.getMethods();
		Method[] methods= cl.getDeclaredMethods();
		for(Method m:methods)
		{
			Class retType= m.getReturnType();
			String name=m.getName();
			System.out.print("	");
			String modifiers=Modifier.toString(m.getModifiers());
			if(modifiers.length()>0)	
				System.out.print(modifiers +" ");
			System.out.print(retType.getName()+" "+name+"(");
			Class[] paramTypes=m.getParameterTypes();
			for(int j = 0;j<paramTypes.length;j++)
			{
				if(j>0)
					System.out.print(", ");
				System.out.print(paramTypes[j].getName());
			}
			System.out.println(");");
		}
	}
	public static void printFields(Class cl) {
		Field[] fields=cl.getDeclaredFields();
		for(Field f:fields)
		{
			Class type=f.getType();
			String name=f.getName();
			System.out.print("	");
			String modifiers=Modifier.toString(f.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers+" ");
			System.out.println(type.getName()+" "+name+";");
		}
	}

}

上面的demo用的是getDeclareFields、getDeclareMethods和getDeclareContructors方法, 包含本類的私有和受保護成員, 但不包括其父類成員, 我們把上述demo的 對應方法全換成getFields,getMethods和getContructors看看效果:

 

因為Double的成員太多了, 帶上父類成員就更多了, 為了清晰,我又寫了一個父類和子類做例子:

父類是這樣式兒的:

package test;

public class Father 
{
	public int father_public_field;
	int father_default_field;
	
	public Father() {
		
	}
	
	public void father_public_method() {
		
	}
	private void father_private_method() {
			
	}
}

 子類是這樣式兒的:

package test;

public class Son extends Father 
{
	public int son_public_field;
	int son_default_field;
	
}

簡單吧, 注意兩個類的修飾符, 我們把上面的demo對應方法換成getFields,getMethods和getContructors:

可以看到只返回了公有成員, 連Son的預設成員都沒有,更別說私有的了

同樣需要注意的是 ,返回的不止有Father類和Son類的成員, 還有Object類的成員(wait(),notify().......), 也就是說上述的"父類"不單單指直接父親, 而是家族樹向上一直到Object類(JAVA所有類的祖宗!), Father沒有顯式繼承所以Father預設繼承了Object, 否則返回的包含Son, Father, Fahter的父類, Fahter的父類的父類.....Object類的所有公有成員

怎麼樣,就問你可怕不可怕??? 

有人會說: 這樣也只是能看到結構而已, 又有什麼用呢,所以上面說了, 搭配代理使用更可怕!