源码角度分析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)
@CallerSensitivepublic 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 volatileif (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{@Overridepublic Object invoke(Object obj,Object[] args) throws IllegalArgumentException,InvocationTargetException{ReflectTest.foo();return null;}}
