一、概念
java程序運行時動態的創建類並調用類的方法和屬性
二、原理簡介
Class<?> clz = Class.forName("java.util.ArrayList");
ArrayList object = (ArrayList) clz.newInstance();
Method method = clz.getMethod("add",Object.class);
method.invoke(list , "sss");
上面就是我們最常見的反射的例子,前兩行實現了類的裝載、鏈接(驗證、准備、解析)、初始化(newInstance其實也是通過反射調用類的<init>方法),后面兩行實現了從class對象中獲取對象然后執行反射調用。
設想,假如我們要實現Invoke方法,是不是只要實現如下類即可:
public class Method {
public void invoke(Object obj , Object... args) {
ArrayList list = (ArrayList)obj;
list.add(args);
}
}
反射的原理之一:就是動態的生成類似於上述的字節碼,加載到JVM中運行
獲取Method對象流程
上面的Class對象是在加載類時由JVM構造的,JVM為每個類管理一個獨一無二的CLASS對象,這份CLASS對象里維護着該類的所有
Method,Field,Constructor的cache,這份cache也可以稱作為根對象。每次getMethod獲取到的Method對象都持有對根對象的引用,因為一些重量級的Method的成員變量(主要是MethodAccessor),我們不希望每次創建Method對象都要重新初始化,於是所有代表同一個方法的Method對象都共享着根對象的MethodAccessor,每一次創建都會調用根對象的copy方法復制一份:
Method copy() {
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot, signature,
annotations, parameterAnnotations, annotationDefault);
res.root = this;
res.methodAccessor = methodAccessor;
return res;
}
調用invoke方法流程
method.invoke方法會首先獲取一個MethodAccessor,首先會從Method的根對象中獲取MethodAccessor,如果為空,用reflectionFactory.newMethodAccessor返回DelegatingMethodAccessorImpl實例,然后將MethodAccessor賦值給Method的root對象中(因為MethodAccessor是所有Method共用的),然后調用DelegatingMethodAccessorImpl中的invoke方法,當調用invoke的次數大於15次以后,MethodAccessor將由java代碼生成
整體流程圖:
