乐趣区

第17部分反射机制

一、类的加载

1. 概述

  • 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化

2. 加载

  • 就是指将 class 文件读入内存,并为之创建一个 Class 对象
  • 任何类被使用时系统都会建立一个 Class 对象——字节码文件对象

3. 连接

  • 验证——确保被加载类的正确性
  • 准备——负责为类的静态成员分配内存,并设置默认初始化值,给给对象分配空间
  • 解析——将类中的符号引用替换为直接引用

4. 初始化

  • 就是以前讲过的初始化步骤

5. 类的加载时机

  • 创建类的实例
  • 访问类的静态变量
  • 调用类的静态方法
  • 使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象
  • 初始化某个类的子类,子类父类都加载
  • 直接使用 java.exe 命令来运行某个主类

二、类加载器

1. 概述

  • 负责将.class 文件加载到内存中,并为之生成对应的 Class 对象

2. 类加载器的组成

  • Bootstrap ClassLoader——根类加载器
  • Extension ClassLoader——扩展类加载器
  • System ClassLoader——系统类加载器

3.Bootstrap ClassLoader 的作用

  • Bootstrap ClassLoader——根类加载器,也被称为引导类加载器,负责 Java 核心类的加载,比如 System,String 等。
  • 在 JDK 中 JRE 的 lib 目录下 rt.jar 文件中

4.Extension ClassLoader 的作用

  • Extension ClassLoader——扩展类加载器,负责 JRE 的扩展目录中 jar 包的加载。
  • 在 JDK 中 JRE 的 lib 目录下 ext 目录。

5.System ClassLoader 的作用

  • System ClassLoader——系统类加载器,负责在 JVM 启动时加载来自 java 命令的 class 文件。

三、Class 类

1. Class 类的全称

public final class Class<T> extends Object 
implements Serializable, GenericDeclaration, Type, AnnotatedElement

2. Class 类的概述

  • Java 程序在运行时,Java 运行时系统一直对所有的对象进行所谓的运行时类型标识。
  • 这项信息纪录了每个对象所属的类。
  • 虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是 Class 类。
  • Class 类封装一个对象和接口运行时的状态,当装载类时,Class 类型的对象自动创建。
  • Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个 Class 对象。
  • 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
  • 每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
  • 一般某个类的 Class 对象被载入内存,它就用来创建这个类的所有对象。

3. Class 类的构造方法

 无公共的构造方法 

4. Class 类的成员方法

4.01 getConstructor(Class<?>… parameterTypes)

 方法:* public Constructor<T> getConstructor(Class<?>... parameterTypes)
      throws NoSuchMethodException,SecurityException
功能:* 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。* parameterTypes 参数是 Class 对象的一个数组,这些 Class 对象按声明顺序标识构造方法的形参类型。* 如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实例。* 要反映的构造方法是此 Class 对象所表示的类的公共构造方法,其形参类型与 parameterTypes 所指定的参数类型相匹配。参数:* parameterTypes- 参数数组 
返回:* 与指定的 parameterTypes 相匹配的公共构造方法的 Constructor 对象 
抛出:* NoSuchMethodException- 如果找不到匹配的方法。* SecurityException- 如果存在安全管理器 s,并满足下列任一条件:* 调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问构造方法 
        * 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.02 getConstructors()

 方法:* public Constructor<?>[] getConstructors() throws SecurityException
功能:* 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。* 如果该类没有公共构造方法,或者该类是一个数组类,或者该类反映一个基本类型或 void,则返回一个长度为 0 的       数组。* 此方法返回 Constructor<T> 对象的数组(即取自此类构造方法的数组)时,此方法的返回类型                   Constructor<?>[],不是预期的 Constructor<T>[]。* 此少量信息的返回类型是必需的,因为从此方法返回之后,该数组可能被修改以保存不同类的 Constructor 对         象,而这将违反 Constructor<T>[] 的类型保证。返回:* 表示此类公共构造方法的 Constructor 对象数组 
抛出:* SecurityException- 如果存在安全管理器 s,并满足下列任一条件:* 调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问该类中的构造方法 
        * 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用           拒绝访问该类的包 

4.03 getDeclaredConstructor(Class<?>… parameterTypes)

 方法:* public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
      throws NoSuchMethodException,SecurityException
功能:* 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。* parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识构造方法的形参类型。* 如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实例。参数:* parameterTypes- 参数数组 
返回:* 带有指定参数列表的构造方法的 Constructor 对象 
抛出:* NoSuchMethodException- 如果找不到匹配的方法。* SecurityException- 如果存在安全管理器 s,并满足下列任一条件:* 调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问已声明的构造方法 
        * 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用           拒绝访问该类的包 

4.04 getDeclaredConstructors()

 方法:* public Constructor<?>[] getDeclaredConstructors() throws SecurityException
功能:* 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。* 它们是公共、保护、默认(包)访问和私有构造方法。* 返回数组中的元素没有排序,也没有任何特定的顺序。* 如果该类存在一个默认构造方法,则它包含在返回的数组中。* 如果此 Class 对象表示一个接口、一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。返回:* 表示此类所有已声明的构造方法的 Constructor 对象的数组 
抛出:* SecurityException- 如果存在安全管理器 s,并满足下列任一条件:* 调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问该类中已声明的构造方法 
        * 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用           拒绝访问此类的包 

4.05 getField(String name)

 方法:* public Field getField(String name) throws NoSuchFieldException,SecurityException
功能:* 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。* name 参数是一个 String,用于指定所需字段的简称。要反映的字段由下面的算法确定。设 C 为此对象所表示的类:如果 C 声明一个带有指定名的公共字段,则它就是要反映的字段。如果在第 1 步中没有找到任何字段,则该算法被递归地应用于 C 的每一个直接超接口。直接超接口按其声明顺序进行搜索。如果在第 1、2 两步没有找到任何字段,且 C 有一个超类 S,则在 S 上递归调用该算法。如果 C 没有超类,则抛出 NoSuchFieldException。请参阅 Java Language Specification 的第 8.2 和 8.3 节。参数:* name- 字段名 
返回:* 由 name 指定的该类的 Field 对象 
抛出:* NoSuchFieldException- 如果没有找到带有指定名的字段。* NullPointerException- 如果 name 为 null 
    * SecurityException- 如果存在安全管理器 s,并满足下列任一条件:* 调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问字段 
        * 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用            拒绝访问该类的包 

4.06 getFields()

 方法:* public Field[] getFields() throws SecurityException
功能:* 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组。特别地,如果该 Class 对象表示一个类,则此方法返回该类及其所有超类的公共字段。如果该 Class 对象表示一个接口,则此方法返回该接口及其所有超接口的公共字段。该方法不反映数组类的隐式长度字段。用户代码应使用 Array 类的方法来操作数组。请参阅 Java Language Specification 的第 8.2 和 8.3 节。返回:表示公共字段的 Field 对象的数组 
抛出:SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问该类中的字段 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.07 getDeclaredField()

public Field getDeclaredField(String name)
                       throws NoSuchFieldException,
                              SecurityException 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。name 参数是一个 String,它指定所需字段的简称。注意,此方法不反映数组类的 length 字段。参数:name - 字段名 
返回:此类中指定字段的 Field 对象 
抛出:NoSuchFieldException - 如果找不到带有指定名称的字段。NullPointerException - 如果 name 为 null 
SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问已声明字段 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.08 getDeclaredFields()

public Field[] getDeclaredFields()
                          throws SecurityException 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。请参阅 Java Language Specification 的第 8.2 和 8.3 节。返回:表示此类所有已声明字段的 Field 对象的数组 
抛出:SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问此类中已声明的字段 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.09 getMethod()

public Method getMethod(String name,
                        Class<?>... parameterTypes)
                 throws NoSuchMethodException,
                        SecurityException 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。如果 name 是 "<init>;" 或 "<clinit>",则将引发 NoSuchMethodException。否则,要反映的方法由下面的算法确定(设 C 为此对象所表示的类):在 C 中搜索任一匹配的方法。如果找不到匹配的方法,则将在 C 的超类上递归调用第 1 步算法。如果在第 1 步中没有找到任何方法,则在 C 的超接口中搜索匹配的方法。如果找到了这样的方法,则反映该方法。在 C 类中查找匹配的方法:如果 C 正好声明了一个具有指定名称的公共方法并且恰恰有相同的形参类型,则它就是反映的方法。如果在 C 中找到了多个这样的方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则反映该方法;否则将从中任选一个方法。注意,类中可以有多个匹配方法,因为尽管 Java 语言禁止类声明带有相同签名但不同返回类型的多个方法,但 Java 虚拟机并不禁止。这增加了虚拟机的灵活性,可以用来实现各种语言特性。例如,可以使用桥方法 (brige method) 实现协变返回;桥方法以及将被重写的方法将具有相同的签名,不同的返回类型。请参阅 Java 语言规范 第 8.2 和 8.4 节。参数:name - 方法名
parameterTypes - 参数列表 
返回:与指定的 name 和 parameterTypes 匹配的 Method 对象 
抛出:NoSuchMethodException - 如果找不到匹配的方法,或者方法名为 "<init>" 或 "<clinit>" 
NullPointerException - 如果 name 为 null 
SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问方法 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.10 getMethods()

 方法:* public Method[] getMethods() throws SecurityException
功能:* 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。数组类返回从 Object 类继承的所有(公共)member 方法。返回数组中的元素没有排序,也没有任何特定的顺序。如果此 Class 对象表示没有公共成员方法的类或接口,或者表示一个基本类型或 void,则此方法返回长度为 0 的数组。类初始化方法 <clinit> 不包含在返回的数组中。如果类声明了带有相同参数类型的多个公共成员方法,则它们都会包含在返回的数组中。请参阅 Java Language Specification 的第 8.2 和 8.4 节。返回:表示此类中公共方法的 Method 对象的数组 
抛出:SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问该类中的方法 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.11 getDeclaredMethod()

public Method getDeclaredMethod(String name,
                                Class<?>... parameterTypes)
                         throws NoSuchMethodException,
                                SecurityException 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。name 参数是一个 String,它指定所需方法的简称,parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形参类型。如果在某个类中声明了带有相同参数类型的多个方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则返回该方法;否则将从中任选一个方法。如果名称是 "<init>”或“<clinit>",则引发一个 NoSuchMethodException。参数:name - 方法名
parameterTypes - 参数数组 
返回:该类与指定名和参数相匹配的方法的 Method 对象 
抛出:NoSuchMethodException - 如果找不到匹配的方法。NullPointerException - 如果 name 为 null 
SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问已声明方法 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

4.12 getDeclaredMethods()

 方法:* public Method[] getDeclaredMethods() throws SecurityException
功能:* 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何方法,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。类初始化方法 <clinit> 不包含在返回数组中。如果该类声明带有相同参数类型的多个公共成员方法,则它们都包含在返回的数组中。请参阅 Java Language Specification 第 8.2 节。返回:表示此类所有声明方法的 Method 对象的数组 
抛出:SecurityException - 如果存在安全管理器 s,并满足下列任一条件:调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问该类中已声明的方法 
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

四、Constructor 类

1. Constructor 类的全称

public final class Constructor<T> extends AccessibleObject 
implements GenericDeclaration, Member

2. Constructor 类的概述

3. Constructor 类的构造方法

4. Constructor 类的成员方法

4.01 equals(Object obj)

 方法:* public boolean equals(Object obj)
功能:* 将此 Constructor 对象与指定的对象进行比较。* 如果对象相同,则返回 true。* 如果由相同的类声明并且具有相同的形参类型,那么这两个 Constructor 对象是相同的。重写:* 类 Object 中的 equals
参数:* obj- 要与之比较的引用对象。返回:* 如果此对象与 obj 参数相同,则返回 true;否则返回 false。

4.02 getAnnotation(Class<T> annotationClass)

 方法:* public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
功能:* 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。指定者:* AnnotatedElement 接口中的 getAnnotation,Constructor 类继承 AccessibleObject 类,AccessibleObject 类实现了 AnnotatedElement 接口。覆盖:* 类 AccessibleObject 中的 getAnnotation
参数:* annotationClass- 对应于注释类型的 Class 对象 
返回:* 如果该元素的指定注释类型的注释存在于此对象上,则返回这些注释,否则返回 null 
抛出:* NullPointerException- 如果给定的注释类为 null

4.03 getDeclaredAnnotations()

 方法:* public Annotation[] getDeclaredAnnotations()
功能:* 返回直接存在于此元素上的所有注释。* 与此接口中的其他方法不同,该方法将忽略继承的注释。如果没有注释直接存在于此元素上,则返回长度为零的一个数组。* 该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。指定者:* 接口 AnnotatedElement 中的 getDeclaredAnnotations
覆盖:* 类 AccessibleObject 中的 getDeclaredAnnotations
返回:* 直接存在于此元素上的所有注释 

4.04 getDeclaringClass()

 方法:* public Class<T> getDeclaringClass()
功能:* 返回 Class 对象,该对象表示声明由此 Constructor 对象表示的构造方法的类。指定者:* 接口 Member 中的 getDeclaringClass
返回:* 表示声明底层成员的类的对象 

4.05 getExceptionTypes()

 方法:* public Class<?>[] getExceptionTypes()
功能:* 返回一组表示声明要抛出的异常类型的 Class 对象,这些异常是由此对象表示的底层构造方法抛出的。* 如果该构造方法声明其 throws 子句中没有任何异常,则返回一个长度为 0 的数组。返回:* 声明由此对象表示的构造方法抛出的异常类型 

4.06 getGenericExceptionTypes()

 方法:* public Type[] getGenericExceptionTypes()
功能:* 返回一组 Type 对象,这些对象表示声明要由此 Constructor 对象抛出的异常。* 如果底层方法声明其 throws 子句中没有任何异常,则返回一个长度为 0 的数组。* 如果异常类型是一个参数化类型,那么为它返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。* 如果异常的类型是一个类型变量或是一个参数化类型,则创建它。否则将解析它。返回:* 表示底层方法抛出的异常类型的一组 Type 对象 
抛出:* TypeNotPresentException- 如果底层方法的 throws 子句引用了不存在的类型声明 

4.07 getGenericParameterTypes()

 方法:* public Type[] getGenericParameterTypes()
功能:* 按照声明顺序返回一组 Type 对象,这些对象表示此 Constructor 对象所表示的方法的形参类型。如果底层方法不带任何参数,则返回一个长度为 0 的数组。如果形参类型是一个参数化类型,那么为它返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。如果形参类型是一个类型变量或者是一个参数化类型,则创建它。否则将解析它。返回:按照声明顺序返回一组 Type 对象,该对象表示底层方法的形参类型 
抛出:GenericSignatureFormatError - 如果这个一般方法的签名不符合 Java Virtual Machine Specification, 3rd edition 指定的格式 
TypeNotPresentException - 如果任何底层方法的参数类型引用了不存在的类型声明 
MalformedParameterizedTypeException - 如果任何底层方法的参数类型引用了因某种原因而无法实例化的参数化类型 

4.08 getModifiers()

public int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。应该使用 Modifier 类对这些修饰符进行解码。指定者:接口 Member 中的 getModifiers
返回:底层成员的 Java 语言修饰符 

4.09 getName()

 方法:* public String getName()
功能:* 以字符串形式返回此构造方法的名称。* 它总是与构造方法的声明类的简单名称相同。指定者:* 接口 Member 中的 getName
返回:* 底层成员的简单名称 

4.10 getParameterAnnotations()

public Annotation[][] getParameterAnnotations() 按照声明顺序返回一组数组,这些数组表示通过此 Constructor 对象表示的方法的形参上的注释。(如果底层方法没有参数,则返回一个长度为零的数组。如果该方法有一个或多个参数,则为每个不带注释的参数返回一个长度为零的嵌套数组。)包含在返回数组中的注释对象是可序列化的。此方法的调用者可以自由地修改返回的数组;它对返回给其他调用者的数组没有影响。返回:按照声明顺序返回的一组数组,这些数组表示此 Constructor 对象表示的方法的形参上的注释 

4.11 getParameterTypes()

public Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。如果底层构造方法不带任何参数,则返回一个长度为 0 的数组。返回:此对象表示的构造方法的参数类型 

4.12 getTypeParameters()

public TypeVariable<Constructor<T>>[] getTypeParameters() 按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 对象所表示的一般声明来声明的类型变量。如果底层一般声明未声明任何类型的变量,则返回一个长度为 0 的数组。指定者:接口 GenericDeclaration 中的 getTypeParameters
返回:表示通过此一般声明来声明的类型变量的一组 TypeVariable 对象 
抛出:GenericSignatureFormatError - 如果此一般声明的一般签名不符合 Java Virtual Machine Specification, 3rd edition 指定的格式 

4.13 hashCode()

public int hashCode() 返回此 Constructor 的哈希码。该哈希码与底层构造方法的声明类名的哈希码相同。覆盖:类 Object 中的 hashCode
返回:此对象的一个哈希码值。

4.14 isSynthetic()

public boolean isSynthetic() 如果此构造方法是一个复合构造方法,则返回 true;否则返回 false。指定者:接口 Member 中的 isSynthetic
返回:当且仅当此构造方法是按照 Java Language Specification 定义的复合构造方法时才返回 true。

4.15 isVarArgs()

 方法:* public boolean isVarArgs()
功能:* 如果声明此构造方法可以带可变数量的参数,则返回 true;否则返回 false。返回:* 当且仅当声明此构造方法可以带可变数量的参数时才返回 true。

4.16 newInstance(Object… initargs)

 方法:* public T newInstance(Object... initargs) throws InstantiationException,
                                                         IllegalAccessException,
                                                        IllegalArgumentException,
                                                        InvocationTargetException
功能:* 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换。如果底层构造方法所需形参数为 0,则所提供的 initargs 数组的长度可能为 0 或 null。如果构造方法的声明类是非静态上下文的内部类,则构造方法的第一个参数需要是封闭实例;请参阅 Java 语言规范 第 15.9.3 节。如果所需的访问检查和参数检查获得成功并且实例化继续进行,这时构造方法的声明类尚未初始化,则初始化这个类。如果构造方法正常完成,则返回新创建且已初始化的实例。参数:initargs - 将作为变量传递给构造方法调用的对象数组;基本类型的值被包装在适当类型的包装器对象(如 Float 中的 float)中。返回:通过调用此对象表示的构造方法来创建的新对象 
抛出:IllegalAccessException - 如果此 Constructor 对象实施 Java 语言访问控制并且底层构造方法是不可访问的。IllegalArgumentException - 如果实参和形参的数量不同;如果基本参数的解包转换失败;如果在可能的解包后,无法通过方法调用转换将参数值转换为相应的形参类型;如果此构造方法属于枚举类型。InstantiationException - 如果声明底层构造方法的类表示抽象类。InvocationTargetException - 如果底层构造方法抛出异常。ExceptionInInitializerError - 如果此方法引发的初始化失败。

4.17 toGenericString()

public String toGenericString() 返回描述此 Constructor 的字符串,其中包括类型参数。该字符串是作为构造方法访问修饰符(如果有)格式化的,其后面是构造方法的类型参数(如果有)的加尖括号的、逗号分隔的列表,再往后是声明类的完全限定名,再往后是该构造方法的一般形参类型的加括号的、逗号分隔的列表。空格用来分隔访问修饰符与访问修饰符,以及访问修饰符与类型参数或返回值。如果没有类型参数,则省略类型参数列表;如果存在类型参数列表,则用空格分隔列表与类名。如果声明构造方法抛出异常,则参数列表后跟着一个空格,再往后是单词 "throws",再往后是用逗号分隔的所抛出异常类型的列表。构造方法唯一可能的修饰符是访问修饰符 public、protected 或 private。这些修饰符只能出现一个,或者一个也不出现(如果构造方法具有默认(包)访问权)。返回:描述此 Constructor 的字符串,其中包括类型参数 

4.18 toString()

 方法:* public String toString()
功能:* 返回描述此 Constructor 的字符串。* 该字符串是作为构造方法访问修饰符(如果有)格式化的,其后面是声明类的完全限定名,再往后是构造方法形参       类型的加括号的、逗号分隔的列表。* 构造方法唯一可能的修饰符是访问修饰符 public、protected 或 private。* 这些修饰符只能出现一个,或者一个也不出现(如果构造方法具有默认(包)访问权)。覆盖:* 类 Object 中的 toString。返回:* 该对象的字符串表示形式。

五、Field 类

1. Field 类的全称

public final class Field extends AccessibleObject 
implements Member

2. Field 类的概述

3. Field 类的构造方法

4. Field 类的成员方法

4.01 get()

 方法:* public Object get(Object obj) 
      throws IllegalArgumentException,IllegalAccessException
功能:* 返回指定对象上此 Field 表示的字段的值。* 如果该值是一个基本类型值,则自动将其包装在一个对象中。* 底层字段的值是按以下方式获得的:* 如果底层字段是一个静态字段,则忽略 obj 变量;它可能为 null。* 否则,底层字段是一个实例字段。如果指定的 obj 变量为 null,则该方法将抛出一个 NullPointerException。如果指定对象不是声明底层字段的类或接口的实例,则该方法将抛出一个 IllegalArgumentException。如果此 Field 对象强制实施 Java 语言访问控制,并且底层字段是不可访问的,则该方法将抛出一个 IllegalAccessException。如果底层字段是静态的,并且声明该字段的类尚未初始化,则初始化这个类。否则,从底层实例字段或静态字段中获取该值。如果该字段是一个基本类型字段,则在返回前将该值包装在一个对象中,否则照原样返回。如果字段隐藏在 obj 的类型中,则根据前面的规则获得字段的值。参数:* obj- 从中提取所表示字段的值的对象 
返回:* 对象 obj 中的所表示字段的值;在返回之前,基值包装在一个适当的对象中 
抛出:* IllegalAccessException - 如果底层字段是不可访问的。* IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例。* NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。* ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.02 getByte()

public byte getByte(Object obj)
             throws IllegalArgumentException,
                    IllegalAccessException 获取一个静态或实例 byte 字段的值。参数:obj - 从中提取 byte 值的对象 
返回:byte 字段的值 
抛出:IllegalAccessException - 如果底层字段是不可访问的。IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例,或者无法通过扩展转换将字段值转换为 byte 类型。NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.03 getChar()

public char getChar(Object obj)
             throws IllegalArgumentException,
                    IllegalAccessException 获取 char 类型或另一个通过扩展转换可以转换为 char 类型的基本类型的静态或实例字段的值。参数:obj - 从中提取 char 值的对象 
返回:转换为 char 类型的字段的值 
抛出:IllegalAccessException - 如果底层字段是不可访问的。IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例,或者无法通过扩展转换将字段值转换为 char 类型。NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.04 set()

public void set(Object obj,
                Object value)
         throws IllegalArgumentException,
                IllegalAccessException 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。如果底层字段的类型为基本类型,则对新值进行自动解包。进行此操作的方式如下:如果底层字段是静态字段,则忽略 obj 变量;它可能为 null。否则底层字段是一个实例字段。如果指定对象变量为 null,则该方法将抛出一个 NullPointerException。如果指定对象变量不是声明底层字段的类或接口的实例,则该方法将抛出一个 IllegalArgumentException。如果此 Field 对象实施 Java 语言访问控制,并且底层字段是不可访问的,则该方法将抛出一个 IllegalAccessException。如果底层字段为 final 字段,则该方法将抛出一个 IllegalAccessException,除非 setAccessible(true) 已经继承该字段并且该字段是一个非静态字段。在通过程序的其他部分可以访问类的实例之前,只有使用空白 final 字段反序列化或重构类的实例期间,以这种方式设置 final 字段才有意义。在其他任何上下文中使用该方法都可能会有不可预知的结果,包括程序的其他部分继续使用该字段的原始值的情况。如果底层字段的类型为某一基本类型,则可以尝试使用解包转换将新值转换为基本类型的值。如果该尝试失败,则此方法将抛出一个 IllegalArgumentException。如果在进行可能的解包之后,无法通过某一标识或扩展转换将新值转换为底层字段的类型,则此方法将抛出一个 IllegalArgumentException。如果底层字段是静态的,并且声明该字段的类尚未初始化,则初始化这个类。字段被设置为可能已解包并扩大的新值。如果字段隐藏在 obj 的类型中,则根据前面的规则设置字段的值。参数:obj - 应该修改其字段的对象
value - 正被修改的 obj 的字段的新值 
抛出:IllegalAccessException - 如果底层字段是不可访问的。IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例,或者解包转换失败。NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.05 setBoolean()

public void setBoolean(Object obj,
                       boolean z)
                throws IllegalArgumentException,
                       IllegalAccessException 将字段的值设置为指定对象上的一个 boolean 值。该方法等同于 set(obj, zObj),其中 zObj 是一个 Boolean 对象,并且 zObj.booleanValue() == z。参数:obj - 应该修改其字段的对象
z - 正被修改的 obj 的字段的新值 
抛出:IllegalAccessException - 如果底层字段是不可访问的。IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例,或者解包转换失败。NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.06 setByte()

public void setByte(Object obj,
                    byte b)
             throws IllegalArgumentException,
                    IllegalAccessException 将字段的值设置为指定对象上的一个 byte 值。该方法等同于 set(obj, bObj),其中 bObj 是一个 Byte 对象,并且 bObj.byteValue() == b。参数:obj - 应该修改其字段的对象
b - 正被修改的 obj 的字段的新值 
抛出:IllegalAccessException - 如果底层字段是不可访问的。IllegalArgumentException - 如果指定对象不是声明底层字段(或者其子类或实现者)的类或接口的实例,或者解包转换失败。NullPointerException - 如果指定对象为 null 并且字段是一个实例字段。ExceptionInInitializerError - 如果此方法引起的初始化失败。

4.07 getName()

 方法:* public String getName() 以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。如果此类对象表示的是非数组类型的引用类型,则返回该类的二进制名称,Java Language Specification, Second Edition 对此作了详细说明。如果此类对象表示一个基本类型或 void,则返回的名字是一个与该基本类型或 void 所对应的 Java 语言关键字相同的 String。如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。元素类型名的编码如下:Element Type       Encoding  
boolean       Z  
byte       B  
char       C  
class or interface       Lclassname;  
double       D  
float       F  
int       I  
long       J  
short       S  

类或接口名 classname 是上面指定类的二进制名称。示例:String.class.getName()
     returns "java.lang.String"
 byte.class.getName()
     returns "byte"
 (new Object[3]).getClass().getName()
     returns "[Ljava.lang.Object;"
 (new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"
 
返回:此对象所表示的类或接口名。

4.08 getModifiers()

 方法:* public int getModifiers()
功能:* 返回此类或接口以整数编码的 Java 语言修饰符
    * 修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 对应的常量组成;它们应当使用 Modifier 类的方法来解码。* 如果底层类是数组类,则其 public、private 和 protected 修饰符与其组件类型的修饰符相同。如果此 Class 表示一个基本类型或 void,则其 public 修饰符始终为 true,protected 和 private 修饰符始终为 false。如果此对象表示一个数组类、一个基本类型或 void,则其 final 修饰符始终为 true,其接口修饰符始终为 false。该规范没有给定其他修饰符的值。返回:* 表示该类修饰符的 int

六、Method 类

1. Method 类的全称

public final class Method extends AccessibleObject
implements GenericDeclaration, Member

2. Method 类的概述

3. Method 类的构造方法

4. Method 类的成员方法

4.01 invoke()

 方法:* public Object invoke(Object obj,Object... args)
      throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
功能:* 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。* 个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。* 如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。* 如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。* 如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。参数:* obj - 从中调用底层方法的对象
    * args - 用于方法调用的参数 
返回:* 使用参数 args 在 obj 上指派该对象所表示方法的结果 
抛出:* IllegalAccessException- 如果此 Method 对象强制执行 Java 语言访问控制,并且底层方法是不可访问的。* IllegalArgumentException-
            如果该方法是实例方法,且指定对象参数不是声明底层方法的类或接口(或其中的子类或实现程序)的实例;如果实参和形参的数量不相同;如果基本参数的解包转换失败;如果在解包后,无法通过方法调用转换将参数值转换为相应的形参类型。* InvocationTargetException- 如果底层方法抛出异常。* NullPointerException- 如果指定对象为 null,且该方法是一个实例方法。* ExceptionInInitializerError- 如果由此方法引起的初始化失败。

4.02 getName()

 方法:* public String getName()
功能:* 以 String 形式返回此 Method 对象表示的方法名称
指定者:* 接口 Member 中的 getName
返回:* 底层成员的简单名称 

4.03 getModifiers()

 方法:* public int getModifiers()
功能:* 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。* 应该使用 Modifier 类对修饰符进行解码。指定者:* 接口 Member 中的 getModifiers
返回:* 底层成员的 Java 语言修饰符 

4.04 getReturnType()

 方法:* public Class<?> getReturnType()
功能:* 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。返回:* 此对象所表示的方法的返回类型 

4.05 getParameterTypes()

 方法:* public Class<?>[] getParameterTypes()
功能:* 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。* 如果底层方法不带参数,则返回长度为 0 的数组。返回:* 此对象所表示的方法的参数类型 

七、AccessibleObject 类

1. AccessibleObject 类的全称

public class AccessibleObject extends Object
implements AnnotatedElement

2. AccessibleObject 类的概述

AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。

它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

对于公共成员、默认访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。

在反射对象中设置 accessible 标志允许具有足够特权的复杂应用程序(比如 Java Object Serialization 或其他持久性机制)以某种通常禁止使用的方式来操作对象。

3. AccessibleObject 类的构造方法

protected AccessibleObject() 构造方法:仅供 Java 虚拟机使用。

4. AccessibleObject 类的成员方法

4.01 getAnnotation(Class<T> annotationClass)

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) 从接口 AnnotatedElement 复制的描述 
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。指定者:接口 AnnotatedElement 中的 getAnnotation
参数:annotationClass - 对应于注释类型的 Class 对象 
返回:如果该元素的指定注释类型的注释存在于此对象上,则返回这些注释,否则返回 null 
抛出:NullPointerException - 如果给定的注释类为 null

4.02 getAnnotations()

public Annotation[] getAnnotations() 从接口 AnnotatedElement 复制的描述 
返回此元素上存在的所有注释。(如果此元素没有注释,则返回长度为零的数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。指定者:接口 AnnotatedElement 中的 getAnnotations
返回:此元素上存在的所有注释 

4.03 getDeclaredAnnotations()

public Annotation[] getDeclaredAnnotations() 从接口 AnnotatedElement 复制的描述 
返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。指定者:接口 AnnotatedElement 中的 getDeclaredAnnotations
返回:直接存在于此元素上的所有注释 

4.04 isAccessible()

public boolean isAccessible() 获取此对象的 accessible 标志的值。返回:此对象的 accessible 标志的值。

4.05 isAnnotationPresent(Class<? extends Annotation>

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 从接口 AnnotatedElement 复制的描述 
如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。此方法主要是为了便于访问标记注释而设计的。指定者:接口 AnnotatedElement 中的 isAnnotationPresent
参数:annotationClass - 对应于注释类型的 Class 对象 
返回:如果指定注释类型的注释存在于此对象上,则返回 true,否则返回 false 
抛出:NullPointerException - 如果给定的注释类为 null

4.06 setAccessible(AccessibleObject[] array,boolean flag)

public static void setAccessible(AccessibleObject[] array,boolean flag)
                          throws SecurityException 使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。首先,如果存在安全管理器,则在 ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。如果 flag 为 true,但是不能更改输入 array 的任何元素的可访问性(例如,如果元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。如果发生 SecurityException,对于少于(不包括)发生异常的元素的数组元素,可以将对象的可访问性设置为 flag;对于超出(包括)引发异常的元素的那些元素,则不更改其可访问性。参数:array - AccessibleObjects 的数组
flag - 每个对象中的 accessible 标志的新值 
抛出:SecurityException - 如果请求被拒绝。

4.07 setAccessible(boolean flag)

public void setAccessible(boolean flag)
                   throws SecurityException 将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。首先,如果存在安全管理器,则在 ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。如果 flag 为 true,并且不能更改此对象的可访问性(例如,如果此元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。如果此对象是 java.lang.Class 类的 Constructor 对象,并且 flag 为 true,则会引发 SecurityException。参数:flag - accessible 标志的新值 
抛出:SecurityException - 如果请求被拒绝。

八、Modifier 类

1. Modifier 类的全称

public enum Modifier extends Enum<Modifier>

2. Modifier 类的概述

3. Modifier 类的枚举常量

枚举 意义
public static final Modifier PUBLIC 修饰符 public
public static final Modifier PROTECTED 修饰符 protected
public static final Modifier PRIVATE 修饰符 private
public static final Modifier ABSTRACT 修饰符 abstract
public static final Modifier STATIC 修饰符 static
public static final Modifier FINAL 修饰符 final
public static final Modifier TRANSIENT 修饰符 transient
public static final Modifier VOLATILE 修饰符 volatile
public static final Modifier SYNCHRONIZED 修饰符 synchronized
public static final Modifier NATIVE 修饰符 native
public static final Modifier STRICTFP 修饰符 strictfp

4. Modifier 类的成员方法

4.01 toString()

 方法:* public String toString()
功能:* 返回此修饰符的小写名称。覆盖:* 类 Enum<Modifier> 中的 toString
返回:* 枚举常量的名称 

4.02 valueOf(String name)

 方法:* public static Modifier valueOf(String name)
功能:* 返回带有指定名称的该类型的枚举常量。* 字符串必须与用于声明该类型的枚举常量的标识符完全匹配。(不允许有多余的空格。)参数:* 指定要返回的枚举常量的名称。- 
返回:* 返回带有指定名称的枚举常量 
抛出:* IllegalArgumentException- 如果该枚举类型没有带有指定名称的常量 

4.03 values()

 方法:* public static final Modifier[] values()
功能:* 按照声明的顺序返回一个包含此枚举类型常量的数组。此方法可用于迭代常量,如下所示:for(Modifier c : Modifier.values()){System.out.println(c);
      }
返回:* 包含此枚举类型常量的数组,按声明的顺序排列 

九、反射

1. 概述

  • JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java 语言的反射机制。
  • 要想解剖一个类, 必须先要获取到该类的字节码文件对象。而解剖使用的就是 Class 类对象。从而得到其中的方法或成员. 所以先要获取到每一个字节码文件对应的 Class 类型的对象.

2. 获取 Class 类型的对象的方法

  • 方式一
Person p = new Person();
Class clazz = p.getClass();
  • 方式二
Class clazz = Person.class;
  • 方式三
Class clazz = Class.forName("com.chenlianyuan.Person");

3. 通过反射获取构造方法并使用

  • 获取公共的指定的构造方法
Constructor<T> getConstructor(Class<?>... parameterTypes)
  • 获取所有的公共的构造方法
Constructor<?>[] getConstructors()
  • 获取任意一个指定的构造方法 (包括私有)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
  • 获取该类中所有声明的构造方法
Constructor<?>[] getDeclaredConstructors()

4. 通过反射获取成员变量并使用

5. 通过反射获取成员方法并使用

退出移动版