首先要知道RTTI(run-time type identification),即运行时类型识别,用于在运行时识别一个对象的类型和类信息。 不同于编译期间就能确定的对象类型及类信息,java反射允许开发者在运行时发现和使用类的信息。 在运行时,通过类的全限定名,可以构造出制定对象,可以调用该对象的任意属性和方法。 java的反射机制主要提供以下功能:
运行时判断任意一个对象所属的类
运行时构造任意一个类对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
反射基础
在开始讲述java反射之前,先来看一下Class类。
1. Class 类
Class 类位于java.lang中。该类的实例表示java应用运行时的类或者接口。运行时每个类对象在jvm里的表示都是一个Class对象。可以通过类名.class、类型.getClass、Class.forName('类全限定名')等方法获取Class对象。另外数组也被映射为class对象的一个类,所有具有相同元素类型和维度的数组都共享该class对象。基本类型boolean、byte、char、short、int、long、float、double和关键字void也是class对象。
/* * Private constructor. Only the Java Virtual Machine creates Class objects. * This constructor is not used and prevents the default constructor being * generated. */ privateClass(ClassLoader loader, Class<?> arrayComponentType) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; componentType = arrayComponentType; } }
public boolean mqray.learn.cn.service.entity.PersonEntity.equals(java.lang.Object) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.toString() public int mqray.learn.cn.service.entity.PersonEntity.hashCode() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName() public void mqray.learn.cn.service.entity.PersonEntity.setName(java.lang.String) public void mqray.learn.cn.service.entity.PersonEntity.setGender(java.lang.String) public java.lang.Double mqray.learn.cn.service.entity.PersonEntity.getHeight() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getInfo() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getGender() public void mqray.learn.cn.service.entity.PersonEntity.setAge(int) public void mqray.learn.cn.service.entity.PersonEntity.setOccupation(java.lang.String) public int mqray.learn.cn.service.entity.PersonEntity.getAge() public void mqray.learn.cn.service.entity.PersonEntity.setHeight(java.lang.Double) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getOccupation() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final void java.lang.Object.wait() throws java.lang.InterruptedException public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() -------***********---------- public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName() -------***********---------- public boolean mqray.learn.cn.service.entity.PersonEntity.equals(java.lang.Object) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.toString() public int mqray.learn.cn.service.entity.PersonEntity.hashCode() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName() public void mqray.learn.cn.service.entity.PersonEntity.setName(java.lang.String) public void mqray.learn.cn.service.entity.PersonEntity.setGender(java.lang.String) public java.lang.Double mqray.learn.cn.service.entity.PersonEntity.getHeight() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getInfo() private int mqray.learn.cn.service.entity.PersonEntity.getSalary() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getGender() public void mqray.learn.cn.service.entity.PersonEntity.setAge(int) public void mqray.learn.cn.service.entity.PersonEntity.setOccupation(java.lang.String) protected boolean mqray.learn.cn.service.entity.PersonEntity.canEqual(java.lang.Object) public int mqray.learn.cn.service.entity.PersonEntity.getAge() public void mqray.learn.cn.service.entity.PersonEntity.setHeight(java.lang.Double) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getOccupation() -------***********---------- public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName()
public java.lang.String mqray.learn.cn.service.entity.WriterEntity.run() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.write() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.read() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.walk() public boolean mqray.learn.cn.service.entity.PersonEntity.equals(java.lang.Object) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.toString() public int mqray.learn.cn.service.entity.PersonEntity.hashCode() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName() public void mqray.learn.cn.service.entity.PersonEntity.setName(java.lang.String) public void mqray.learn.cn.service.entity.PersonEntity.setAge(int) public void mqray.learn.cn.service.entity.PersonEntity.setOccupation(java.lang.String) public int mqray.learn.cn.service.entity.PersonEntity.getAge() public java.lang.Double mqray.learn.cn.service.entity.PersonEntity.getHeight() public void mqray.learn.cn.service.entity.PersonEntity.setHeight(java.lang.Double) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getGender() public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getInfo() public void mqray.learn.cn.service.entity.PersonEntity.setGender(java.lang.String) public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getOccupation() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final void java.lang.Object.wait() throws java.lang.InterruptedException public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() -------***********---------- public java.lang.String mqray.learn.cn.service.entity.PersonEntity.getName() -------***********---------- public java.lang.String mqray.learn.cn.service.entity.WriterEntity.run() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.write() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.read() public java.lang.String mqray.learn.cn.service.entity.WriterEntity.walk() -------***********---------- public java.lang.String mqray.learn.cn.service.entity.WriterEntity.walk()
@CallerSensitive @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException { SecurityManagersm= System.getSecurityManager(); if (sm != null) { checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); }
// NOTE: the following code may not be strictly correct under // the current Java memory model.
// Constructor lookup if (cachedConstructor == null) { if (this == Class.class) { thrownewIllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; final Constructor<T> c = getReflectionFactory().copyConstructor( getConstructor0(empty, Member.DECLARED)); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged( newjava.security.PrivilegedAction<>() { public Void run() { c.setAccessible(true); returnnull; } }); cachedConstructor = c; } catch (NoSuchMethodException e) { throw (InstantiationException) newInstantiationException(getName()).initCause(e); } } Constructor<T> tmpConstructor = cachedConstructor; // Security check (same as in java.lang.reflect.Constructor) Class<?> caller = Reflection.getCallerClass(); if (newInstanceCallerCache != caller) { intmodifiers= tmpConstructor.getModifiers(); Reflection.ensureMemberAccess(caller, this, this, modifiers); newInstanceCallerCache = caller; } // Run constructor try { return tmpConstructor.newInstance((Object[])null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached returnnull; } } privatetransientvolatile Constructor<T> cachedConstructor; privatetransientvolatile Class<?> newInstanceCallerCache;
接下来,获取类实例: 主体逻辑为:
调用checkMemberAccess校验权限
查找构造器
调用tmpConstructor.newInstance创建类实例 其中第二步中会先判断cachedConstructor数组是否为空,如果为空,则调用 final Constructor<T> c = getReflectionFactory().copyConstructor(getConstructor0(empty, Member.DECLARED)); 其中具体实现如下:
private PublicMethods.MethodList getMethodsRecursive(String name, Class<?>[] parameterTypes, boolean includeStatic) { // 1st check declared public methods Method[] methods = privateGetDeclaredMethods(/* publicOnly */true); PublicMethods.MethodListres= PublicMethods.MethodList .filter(methods, name, parameterTypes, includeStatic); // if there is at least one match among declared methods, we need not // search any further as such match surely overrides matching methods // declared in superclass(es) or interface(s). if (res != null) { return res; }
// if there was no match among declared methods, // we must consult the superclass (if any) recursively... Class<?> sc = getSuperclass(); if (sc != null) { res = sc.getMethodsRecursive(name, parameterTypes, includeStatic); }
// ...and coalesce the superclass methods with methods obtained // from directly implemented interfaces excluding static methods... for (Class<?> intf : getInterfaces(/* cloneArray */false)) { res = PublicMethods.MethodList.merge( res, intf.getMethodsRecursive(name, parameterTypes, /* includeStatic */false)); }
private MethodAccessor acquireMethodAccessor() { // First check to see if one has been created yet, and take it // if so MethodAccessortmp=null; if (root != null) tmp = root.getMethodAccessor(); if (tmp != null) { methodAccessor = tmp; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newMethodAccessor(this); setMethodAccessor(tmp); }