java也是一門編譯型語(yǔ)言,但凡的是編譯型語(yǔ)言,都有著不靈活的一面,不能像js這樣的解釋性語(yǔ)言的動(dòng)態(tài)化,但是編譯型語(yǔ)言都有強(qiáng)大的運(yùn)行時(shí),而反射就是java的運(yùn)行時(shí)的體現(xiàn)。
下面看一個(gè)簡(jiǎn)單的Demo
public static void printClassMethodMessage(Object obj){
Class s = obj.getClass();
System.out.println(s.getName());
//獲取所有的方法數(shù)組
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()+"(");
//獲取該方法所有的參數(shù)
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1: paramTypes ) {
//獲取每個(gè)參數(shù)的類名
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
最后看一下編譯和運(yùn)行時(shí)的差異
public static void main (String[] args) {
//普通數(shù)組
ArrayList list = new ArrayList();
//只能保存字符串的數(shù)組
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");//可以添加
// list1.add(20); //編譯錯(cuò)誤
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1==c2);
try {
Method m = c2.getMethod("add", Object.class); //利用反射獲取數(shù)組 add 方法
m.invoke(list1,20); //方法調(diào)用
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);// 報(bào)錯(cuò)
}
}catch (Exception e){
e.printStackTrace();
}
}
上面的例子說(shuō)明了,編譯時(shí)和運(yùn)行時(shí)的差別,運(yùn)行時(shí)是有黑魔法的,它可以繞過(guò)編譯去進(jìn)行一些編譯器不允許的操作。
反射的使用場(chǎng)景在spring框架是很廣泛的,例如AOP面向切面編程和動(dòng)態(tài)代理...