源码角度分析Java反射实现原理
Animal animal=new Cat();
获取想要操作的类的对象,通过该类对象可以调用类的任意方法。
调用Class对象所对应的类中定义的方法
使用反射API来获取并调用类的属性和方法等
1.调用某个对象的getClass方法以获取该类对应的Class对象
-
Animal animal = new Animal();
Class clz = animal.getClass();
2.调用某个类的class属性以获取该类对应的Class对象
-
Class clz = Animal.class;
3.调用Class类中的forName静态方法,从而获取对应的Class对象
-
Class clz=Class.forName("ClassPath");
1.使用Class对象的newInstance方法创建该Class对象对应类的实例,这种方法要求该Class对象对应的类有默认的空构造器
-
Class clz=Class.forName("ClassPath");
Animal a=(Animal)clz.newInstance();
2.先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance方法创建Class对象对应类的实例
-
Constructor c = clazz.getDeclaredConstructor(String.class,int.class);
Cat cat = (Cat) c.newInstance("美国短尾猫","2");
获取Method对象:通过调用Class对象的getMethod(String name,Class<?>... parameterTypes)返回一个Method对象,他描述了此Class对象所表示的类或接口指定的公共成员方法。其中name参数是指所需方法的名称,parameterTypes参数是按照声明顺序标识该方法的形参类型的Class对象的一个数组。
调用invoke方法:通过调用Method对象的invoke方法来动态执行函数
-
//首先获取类对象
Class clz = Class.forName("Animal");
//获取类对象的setName方法
Method method = clz.getMethod("setName", String.class);
//获取构造器对象
Constructor constructor = clz.getConstructor();
//根据构造器对象生成实体对象
Animal animal = (Animal) constructor.newInstance();
//通过方法对象的invoke函数对实体对象方法进行动态调用
method.invoke(animal, "美国蓝白猫");
public class ReflectionTest {
private static int count=0;
public static void foo(){
new Exception((++count)+"次").printStackTrace();
}
public static void main(String[] args) throws Exception {
Class<?> clz= Class.forName("ReflectionTest");
Method method=clz.getMethod("foo");
for(int i=0;i<20;i++){
method.invoke(null);
}
}
}
java.lang.Exception: 16次
at com.Reflection.foo(Reflection.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.Reflection.main(Reflection.java:20)
java.lang.Exception: 17次
at com.Reflection.foo(Reflection.java:13)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.Reflection.main(Reflection.java:20)
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
public interface MethodAccessor {
Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException;
}
class NativeMethodAccessorImpl extends MethodAccessorImpl {
private final Method method;
private DelegatingMethodAccessorImpl parent;
private int numInvocations;
NativeMethodAccessorImpl(Method var1) {
this.method = var1;
}
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
this.parent.setDelegate(var3);
}
return invoke0(this.method, var1, var2);
}
void setParent(DelegatingMethodAccessorImpl var1) {
this.parent = var1;
}
private static native Object invoke0(Method var0, Object var1, Object[] var2);
}
public class GeneratedMethodAccessor1 extends MethodAccessorImpl{
@Override
public Object invoke(Object obj,Object[] args) throws IllegalArgumentException,InvocationTargetException{
ReflectTest.foo();
return null;
}
}