java也是一門編譯型語言,但凡的是編譯型語言,都有著不靈活的一面,不能像js這樣的解釋性語言的動態化,但是編譯型語言都有強大的運行時,而反射就是java的運行時的體現。
下面看一個簡單的Demo
public static void printClassMethodMessage(Object obj){
Class s = obj.getClass();
System.out.println(s.getName());
//獲取所有的方法數組
Method[] ms = s.getMethods();
for (int i=0;i<ms.length;i++){
//獲取該方法的返回值類型
Class returnType = ms[i].getReturnType();
//返回值類型的名字
System.out.print(returnType.getName()+ " ");
//方法名
System.out.print(ms[i].getName()+"(");
//獲取該方法所有的參數
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1: paramTypes ) {
//獲取每個參數的類名
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
最后看一下編譯和運行時的差異
public static void main (String[] args) {
//普通數組
ArrayList list = new ArrayList();
//只能保存字符串的數組
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");//可以添加
// list1.add(20); //編譯錯誤
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1==c2);
try {
Method m = c2.getMethod("add", Object.class); //利用反射獲取數組 add 方法
m.invoke(list1,20); //方法調用
System.out.println(list1.size()); //大小為2
System.out.println(list1);
for (Object ob: list1 ) {
System.out.println(ob); //正常
}
for (String str: list1 ) {
System.out.println(str);// 報錯
}
}catch (Exception e){
e.printStackTrace();
}
}
上面的例子說明了,編譯時和運行時的差別,運行時是有黑魔法的,它可以繞過編譯去進行一些編譯器不允許的操作。
反射的使用場景在spring框架是很廣泛的,例如AOP面向切面編程和動態代理...