介绍
如果想要在程序运行阶段访问某个类的所有信息,并支持修改类的状态或者行为的话,肯定会用到反射,而反射靠的就是Class类。
通过Class类可以获取类的实例,构造方法,字段,成员方法,接口等信息。获取之后可以通过API进行相应的操作。
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement
常量&变量
//标识注解类型private static final int ANNOTATION= 0x00002000;//标识枚举类型private static final int ENUM = 0x00004000;//表示该class文件并非由Java源代码所生成private static final int SYNTHETIC = 0x00001000;//注册本地方法private static native void registerNatives();static {registerNatives();}//缓存构造器private volatile transient Constructor<T> cachedConstructor;//调用者的缓存构造器private volatile transient Class<?> newInstanceCallerCache;// cache the name to reduce the number of calls into the VM//实体的名称private transient String name;private native String getName0();// Package-private to allow ClassLoader accessClassLoader getClassLoader0() { return classLoader; }// Initialized in JVM not by private constructor// This field is filtered from reflection access, i.e. getDeclaredField// will throw NoSuchFieldException//类加载器private final ClassLoader classLoader;/** protection domain returned when the internal domain is null *///null值的安全返回private static java.security.ProtectionDomain allPermDomain;/*** Reflection support.*/// Caches for certain reflective results//缓存反射结果private static boolean useCaches = true;//反射信息private volatile transient SoftReference<ReflectionData<T>> reflectionData;// Incremented by the VM on each call to JVM TI RedefineClasses()// that redefines this class or a superclass.//每次调用JVM时由VM递增private volatile transient int classRedefinedCount = 0;// Generic signature handlingprivate native String getGenericSignature0();// Generic info repository; lazily initialized//通用信息private volatile transient ClassRepository genericInfo;/** use serialVersionUID from JDK 1.1 for interoperability *///序列化版本号private static final long serialVersionUID = 3206093459760846163L;/*** Class Class is special cased within the Serialization Stream Protocol.** A Class instance is written initially into an ObjectOutputStream in the* following format:* <pre>* {@code TC_CLASS} ClassDescriptor* A ClassDescriptor is a special cased serialization of* a {@code java.io.ObjectStreamClass} instance.* </pre>* A new handle is generated for the initial time the class descriptor* is written into the stream. Future references to the class descriptor* are written as references to the initial class descriptor instance.** @see java.io.ObjectStreamClass*/private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];//反射工厂private static ReflectionFactory reflectionFactory;// To be able to query system properties as soon as they're available//是否初始化private static boolean initted = false;private static void checkInitted() {if (initted) return;AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {// Tests to ensure the system properties table is fully// initialized. This is needed because reflection code is// called very early in the initialization process (before// command-line arguments have been parsed and therefore// these user-settable properties installed.) We assume that// if System.out is non-null then the System class has been// fully initialized and that the bulk of the startup code// has been run.if (System.out == null) {// java.lang.System not yet fully initializedreturn null;}// Doesn't use Boolean.getBoolean to avoid class init.String val =System.getProperty("sun.reflect.noCaches");if (val != null && val.equals("true")) {useCaches = false;}initted = true;return null;}});}//枚举类常量 nullprivate volatile transient T[] enumConstants = null;//枚举类常量目录private volatile transient Map<String, T> enumConstantDirectory = null;// Annotations cache@SuppressWarnings("UnusedDeclaration")//注解数据private volatile transient AnnotationData annotationData;@SuppressWarnings("UnusedDeclaration")//注解类型private volatile transient AnnotationType annotationType;/* Backing store of user-defined values pertaining to this class.* Maintained by the ClassValue class.*/transient ClassValue.ClassValueMap classValueMap;
构造方法
/** Private constructor. Only the Java Virtual Machine creates Class objects.* This constructor is not used and prevents the default constructor being* generated.*只能由java虚拟机创建对象*/private Class(ClassLoader loader) {// Initialize final field for classLoader. The initialization value of non-null// prevents future JIT optimizations from assuming this final field is null.classLoader = loader;}
Class并不能直接通过new Class()获取实例。那么应该如何获取呢?
//直接通过类的静态变量来获取
Class<Integer> intClass = Integer.class;//通过实例变量的getClass方法
Integer integer = new Integer(0);
Class<? extends Integer> aClass = integer.getClass();//通过Class.forName("类的全限定名")
Class<?> aClass1 = Class.forName("java.lang.Integer");
常用方法
forName
/*** Returns the {@code Class} object associated with the class or* interface with the given string name. Invoking this method is* equivalent to:** <blockquote>* {@code Class.forName(className, true, currentLoader)}* </blockquote>** where {@code currentLoader} denotes the defining class loader of* the current class.** <p> For example, the following code fragment returns the* runtime {@code Class} descriptor for the class named* {@code java.lang.Thread}:** <blockquote>* {@code Class t = Class.forName("java.lang.Thread")}* </blockquote>* <p>* A call to {@code forName("X")} causes the class named* {@code X} to be initialized.** @param className the fully qualified name of the desired class.* @return the {@code Class} object for the class with the* specified name.* @exception LinkageError if the linkage fails* @exception ExceptionInInitializerError if the initialization provoked* by this method fails* @exception ClassNotFoundException if the class cannot be located* 手动加载一个类,*/@CallerSensitivepublic static Class<?> forName(String className)throws ClassNotFoundException {Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}/*** Returns the {@code Class} object associated with the class or* interface with the given string name, using the given class loader.* Given the fully qualified name for a class or interface (in the same* format returned by {@code getName}) this method attempts to* locate, load, and link the class or interface. The specified class* loader is used to load the class or interface. If the parameter* {@code loader} is null, the class is loaded through the bootstrap* class loader. The class is initialized only if the* {@code initialize} parameter is {@code true} and if it has* not been initialized earlier.** <p> If {@code name} denotes a primitive type or void, an attempt* will be made to locate a user-defined class in the unnamed package whose* name is {@code name}. Therefore, this method cannot be used to* obtain any of the {@code Class} objects representing primitive* types or void.** <p> If {@code name} denotes an array class, the component type of* the array class is loaded but not initialized.** <p> For example, in an instance method the expression:** <blockquote>* {@code Class.forName("Foo")}* </blockquote>** is equivalent to:** <blockquote>* {@code Class.forName("Foo", true, this.getClass().getClassLoader())}* </blockquote>** Note that this method throws errors related to loading, linking or* initializing as specified in Sections 12.2, 12.3 and 12.4 of <em>The* Java Language Specification</em>.* Note that this method does not check whether the requested class* is accessible to its caller.** <p> If the {@code loader} is {@code null}, and a security* manager is present, and the caller's class loader is not null, then this* method calls the security manager's {@code checkPermission} method* with a {@code RuntimePermission("getClassLoader")} permission to* ensure it's ok to access the bootstrap class loader.** @param name fully qualified name of the desired class* @param initialize if {@code true} the class will be initialized.* See Section 12.4 of <em>The Java Language Specification</em>.* @param loader class loader from which the class must be loaded* @return class object representing the desired class** @exception LinkageError if the linkage fails* @exception ExceptionInInitializerError if the initialization provoked* by this method fails* @exception ClassNotFoundException if the class cannot be located by* the specified class loader** @see java.lang.Class#forName(String)* @see java.lang.ClassLoader* @since 1.2* boolean initialize 是否对类进行初始化*/@CallerSensitivepublic static Class<?> forName(String name, boolean initialize,ClassLoader loader)throws ClassNotFoundException{Class<?> caller = null;SecurityManager sm = System.getSecurityManager();if (sm != null) {// Reflective call to get caller class is only needed if a security manager// is present. Avoid the overhead of making this call otherwise.caller = Reflection.getCallerClass();if (sun.misc.VM.isSystemDomainLoader(loader)) {ClassLoader ccl = ClassLoader.getClassLoader(caller);if (!sun.misc.VM.isSystemDomainLoader(ccl)) {sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);}}}return forName0(name, initialize, loader, caller);}/** Called after security check for system loader access checks have been made. */private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller)throws ClassNotFoundException;
在使用反射的时候,Class.forName是最常用的一种方式。而Class.forName底层会指向forName0这个本地方法
参数:
(1)name:类的全限定名
(2)initialize:是否初始化这个类
(3)loader:类加载器
(4)caller:调用Class.forName所在类的Class,比如A类代码块里有Class.forName,那么caller就是A的class实例。
getConstructors
/*** Returns an array containing {@code Constructor} objects reflecting* all the public constructors of the class represented by this* {@code Class} object. An array of length 0 is returned if the* class has no public constructors, or if the class is an array class, or* if the class reflects a primitive type or void.** Note that while this method returns an array of {@code* Constructor<T>} objects (that is an array of constructors from* this class), the return type of this method is {@code* Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as* might be expected. This less informative return type is* necessary since after being returned from this method, the* array could be modified to hold {@code Constructor} objects for* different classes, which would violate the type guarantees of* {@code Constructor<T>[]}.** @return the array of {@code Constructor} objects representing the* public constructors of this class* @throws SecurityException* If a security manager, <i>s</i>, is present and* the caller's class loader is not the same as or an* ancestor of the class loader for the current class and* invocation of {@link SecurityManager#checkPackageAccess* s.checkPackageAccess()} denies access to the package* of this class.** @since JDK1.1* 返回构造函数组成的数据*/@CallerSensitivepublic Constructor<?>[] getConstructors() throws SecurityException {//判断是否有访问权限checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);//获取到声明的构造方法,并拷贝一份构造方法return copyConstructors(privateGetDeclaredConstructors(true));}
privateGetDeclaredConstructors()
// Returns an array of "root" constructors. These Constructor// objects must NOT be propagated to the outside world, but must// instead be copied via ReflectionFactory.copyConstructor.private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {//判断是否配置了useCached属性checkInitted();Constructor<T>[] res;//获取缓存当中的数据ReflectionData<T> rd = reflectionData();if (rd != null) {//返回缓存当中的构造方法 根据publicOnly决定是共有还是私有的构造方法res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;if (res != null) return res;}// No cached value available; request value from VMif (isInterface()) {//直接生成一个数组长度为0的Constructor数组 因为接口没有构造方法@SuppressWarnings("unchecked")Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];res = temporaryRes;} else {//从JVM当中读取数据res = getDeclaredConstructors0(publicOnly);}if (rd != null) {//更新缓存reflectionData当中的构造方法if (publicOnly) {rd.publicConstructors = res;} else {rd.declaredConstructors = res;}}return res;}
reflectionData
// Lazily create and cache ReflectionData//创建和缓存反射获得的数据private ReflectionData<T> reflectionData() {//获取当前reflectionDataSoftReference<ReflectionData<T>> reflectionData = this.reflectionData;int classRedefinedCount = this.classRedefinedCount;ReflectionData<T> rd;//如果可以使用缓存,并且缓存当中的数据不为null,而且缓存没有失效,(缓存当中redefinedCount等于classRedefinedCount的值)if (useCaches &&reflectionData != null &&(rd = reflectionData.get()) != null &&rd.redefinedCount == classRedefinedCount) {//直接返回缓存当中的reflectionDatareturn rd;}// else no SoftReference or cleared SoftReference or stale ReflectionData// -> create and replace new instance//创建新的reflectionData,并保存到缓存当中去return newReflectionData(reflectionData, classRedefinedCount);}
newReflectionData
private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,int classRedefinedCount) {//不使用缓存,直接返回if (!useCaches) return null;//while + caswhile (true) {//创建新的ReflectionDataReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);// try to CAS it...//更新成功,返回if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {return rd;}// else retry//否则获得旧的reflectionData和classRedefinedCount的值oldReflectionData = this.reflectionData;classRedefinedCount = this.classRedefinedCount;//如果旧的值不为null, 并且缓存未失效,说明其他线程更新成功了if (oldReflectionData != null &&(rd = oldReflectionData.get()) != null &&rd.redefinedCount == classRedefinedCount) {//直接返回return rd;}}}
newInstance
Constructor.java
获取到Constructor之后,可以通过newInstance的方式获取到实例方法
Constructor.java/*** Uses the constructor represented by this {@code Constructor} object to* create and initialize a new instance of the constructor's* declaring class, with the specified initialization parameters.* Individual parameters are automatically unwrapped to match* primitive formal parameters, and both primitive and reference* parameters are subject to method invocation conversions as necessary.** <p>If the number of formal parameters required by the underlying constructor* is 0, the supplied {@code initargs} array may be of length 0 or null.** <p>If the constructor's declaring class is an inner class in a* non-static context, the first argument to the constructor needs* to be the enclosing instance; see section 15.9.3 of* <cite>The Java™ Language Specification</cite>.** <p>If the required access and argument checks succeed and the* instantiation will proceed, the constructor's declaring class* is initialized if it has not already been initialized.** <p>If the constructor completes normally, returns the newly* created and initialized instance.** @param initargs array of objects to be passed as arguments to* the constructor call; values of primitive types are wrapped in* a wrapper object of the appropriate type (e.g. a {@code float}* in a {@link java.lang.Float Float})** @return a new object created by calling the constructor* this object represents** @exception IllegalAccessException if this {@code Constructor} object* is enforcing Java language access control and the underlying* constructor is inaccessible.* @exception IllegalArgumentException if the number of actual* and formal parameters differ; if an unwrapping* conversion for primitive arguments fails; or if,* after possible unwrapping, a parameter value* cannot be converted to the corresponding formal* parameter type by a method invocation conversion; if* this constructor pertains to an enum type.* @exception InstantiationException if the class that declares the* underlying constructor represents an abstract class.* @exception InvocationTargetException if the underlying constructor* throws an exception.* @exception ExceptionInInitializerError if the initialization provoked* by this method fails.* 获取到实例方法*/@CallerSensitivepublic T newInstance(Object ... initargs)throws InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException{//判断语言级别的访问权限是否被覆盖if (!override) {//没有被覆盖需要检查是否有访问权限if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {Class<?> caller = Reflection.getCallerClass();checkAccess(caller, clazz, null, modifiers);}}//判断是否为枚举类型if ((clazz.getModifiers() & Modifier.ENUM) != 0)//如果是枚举类型不能通过反射创建throw new IllegalArgumentException("Cannot reflectively create enum objects");//获取constructorAccessorConstructorAccessor ca = constructorAccessor; // read volatileif (ca == null) {//如果为null, 通过acquireConstructorAccessor获取ca = acquireConstructorAccessor();}//通过ConstructorAccessor创建实例对象@SuppressWarnings("unchecked")T inst = (T) ca.newInstance(initargs);return inst;}
acquireConstructorAccessor
构建ConstructorAccessor
Constructor.java // NOTE that there is no synchronization used here. It is correct// (though not efficient) to generate more than one// ConstructorAccessor for a given Constructor. However, avoiding// synchronization will probably make the implementation more// scalable.private ConstructorAccessor acquireConstructorAccessor() {// First check to see if one has been created yet, and take it// if so.ConstructorAccessor tmp = null;if (root != null) tmp = root.getConstructorAccessor();if (tmp != null) {//先判断是否已经创建了ConstructorAccessor 如果已经创建了,直接返回获取就可以constructorAccessor = tmp;} else {// Otherwise fabricate one and propagate it up to the root//通过reflectionFactory来创建一个新的ConstructorAccessortmp = reflectionFactory.newConstructorAccessor(this);//设置当前Class对象当中的ConstructorAccessor对象setConstructorAccessor(tmp);}return tmp;}
getDeclaredMethod
获取指定的Method对象方法
/*** Returns a {@code Method} object that reflects the specified* declared method of the class or interface represented by this* {@code Class} object. The {@code name} parameter is a* {@code String} that specifies the simple name of the desired* method, and the {@code parameterTypes} parameter is an array of* {@code Class} objects that identify the method's formal parameter* types, in declared order. If more than one method with the same* parameter types is declared in a class, and one of these methods has a* return type that is more specific than any of the others, that method is* returned; otherwise one of the methods is chosen arbitrarily. If the* name is "<init>"or "<clinit>" a {@code NoSuchMethodException}* is raised.** <p> If this {@code Class} object represents an array type, then this* method does not find the {@code clone()} method.** @param name the name of the method* @param parameterTypes the parameter array* @return the {@code Method} object for the method of this class* matching the specified name and parameters* @throws NoSuchMethodException if a matching method is not found.* @throws NullPointerException if {@code name} is {@code null}* @throws SecurityException* If a security manager, <i>s</i>, is present and any of the* following conditions is met:** <ul>** <li> the caller's class loader is not the same as the* class loader of this class and invocation of* {@link SecurityManager#checkPermission* s.checkPermission} method with* {@code RuntimePermission("accessDeclaredMembers")}* denies access to the declared method** <li> the caller's class loader is not the same as or an* ancestor of the class loader for the current class and* invocation of {@link SecurityManager#checkPackageAccess* s.checkPackageAccess()} denies access to the package* of this class** </ul>** @jls 8.2 Class Members* @jls 8.4 Method Declarations* @since JDK1.1* 获取指定的Method对象方法*/@CallerSensitivepublic Method getDeclaredMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException {//判断当前method是否有访问权限checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);//privateGetDeclaredMethods获取到当前所声明的所有方法//根据当前传递的方法名和参数类型从声明的方法中找到匹配的方法Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);if (method == null) {throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));}//返回return method;}
privateGetDeclaredMethods
// Returns an array of "root" methods. These Method objects must NOT// be propagated to the outside world, but must instead be copied// via ReflectionFactory.copyMethod.//获取类中声明方法具体的实现//publicOnly 是否只获取public方法private Method[] privateGetDeclaredMethods(boolean publicOnly) {//等待系统内部类初始化完成,系统属性(sun.reflect.noCaches)被解析完成checkInitted();Method[] res;//判断当前是否有配置信息ReflectionData<T> rd = reflectionData();if (rd != null) {//从缓存中获取数据res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;if (res != null) return res;}// No cached value available; request value from VM//从JVM当中读取数据 getDeclaredMethods0(publicOnly) 使用native方式读取methods数组对象res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));if (rd != null) {//将缓存当中的数据更新if (publicOnly) {rd.declaredPublicMethods = res;} else {rd.declaredMethods = res;}}return res;}