利用 反射 檢查類的結構 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類
例如,可以使用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類的所有公有成員
怎麼樣,就問你可怕不可怕???
有人會說: 這樣也只是能看到結構而已, 又有什麼用呢,所以上面說了, 搭配代理使用更可怕!