Class源码

news/2025/1/13 2:56:57/

介绍

如果想要在程序运行阶段访问某个类的所有信息,并支持修改类的状态或者行为的话,肯定会用到反射,而反射靠的就是Class类。

通过Class类可以获取类的实例,构造方法,字段,成员方法,接口等信息。获取之后可以通过API进行相应的操作。

public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGXRMgsz-1685746810777)(null)]

常量&变量

    //标识注解类型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&trade; 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 "&lt;init&gt;"or "&lt;clinit&gt;" 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;}

http://www.ppmy.cn/news/180695.html

相关文章

小米12s ultra,索尼xperia1 iv,数码相机 拍照对比

首先说明所有的测试结果和拍摄数据我放到百度网盘了(地址在结尾) 为什么做这个测试 我一直想知道现在的手机和相机差距有多大,到底差在哪儿? 先说结论: 1.1英寸的手机cmos(2022年) 6年前(2016)的入门款相机(m43画幅) 2.手机 不能换镜头,只能在特定的拍摄距离才能发挥出全…

未来三年手机拍摄将超越单反?拍摄建模的时代来了...

如今手机的摄影功能越发强大&#xff0c;慢动作、人像、运动视频、背景虚化、超广角、高倍变焦等需求都不在话下。 所以&#xff0c;一个老生长谈的话题出现&#xff0c;到底何时能追上甚至超越单反&#xff1f; 日前与媒体交流时&#xff0c;高通副总裁 Judd Heape 的观点是&a…

为什么大家拍摄视频不用摄像机,反而选用单反照相机呢?

专业的人&#xff0c;做专业的事&#xff0c; 专业的工具&#xff0c;拍专业的视频&#xff01; 像拍摄视频这种工作&#xff0c;除非你所用的摄像机是专业的&#xff0c;否则拍出来的视频效果&#xff0c;绝对没有单反相机好&#xff0c;别问我为什么&#xff0c;因为索尼摄…

numpy包中的编码函数和解码函数numpy.char.encode() numpy.char.decode()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 numpy包中的编码函数和解码函数 numpy.char.encode() numpy.char.decode() [太阳]选择题 下列代码最后输出的结果是&#xff1f; import numpy as np x np.array([I, Love, Python]) print(…

解压zip,z01,z02

遇到这样的文件需要解压 在win系统上&#xff0c;直接解压后缀名为zip的文件&#xff0c;三个文件的内容都会解压至文件夹&#xff0c;不需要重复操作 若为linux系统需要先将三个文件合并 再对合并文件进行解压 cat data_object_velodyne* > v.zip unzip v.zip 先使用通配…

纪念京九神车Z68、Z67

纪念京九神车Z68、Z67 今天是京九神车Z68最后一次停靠黄州站&#xff0c;1200km&#xff0c;9.5小时&#xff0c;时速120km&#xff0c;夕发朝至&#xff0c;工作生活毫无影响。 从此回家的路&#xff0c;变得遥远而漫长。 发个文章纪念下&#xff01;

ZYNQ-ROM

FPGA本身是SRAM架构&#xff0c;断电后程序就会消失。如何利用FPGA实现 ROM&#xff1f;利用FPGA内部的RAM资源实现ROM,但是不是真正意义上的ROM&#xff0c;而是每次上电都会把初始化的值先写入RAM.使用FPGA内部的ROM,进行数据读取 1、创建ROM初始化文件 ROM,提前准备好数据…

Cpu-Z 官方中文版

Cpu-Z 是一款计算机的CPU检测软件。Cpu-Z适用于任意品牌和型号的监测工作&#xff0c;且检测的数据范围非常广泛、全面&#xff0c;将CPU涉及到的各个方面都以最直观的方式呈现给用户。在新版本中&#xff0c;Cpu-Z还添加了对内存和显卡等硬件部位的检测功能&#xff0c;需要的…