在Java反射机制中,需要掌握的知识有:
(1)掌握反射机制的概述。
(2)能够使用Class类并结合java.lang.reflect包取得一个类的完整结构。
(3)能够使用反射机制实例化对象、动态地调用类中的指定方法和设置属性值。
反射机制的概述
运行时类型信息(RTTI)使得可以在程序运行时发现和使用类型信息。在Java中的RTTI形式包括三种:
(1)传统的类型转换。由RTTI确保类型转换的正确性,如果执行了一个错误的类型转换,就会抛出一个ClassCastException异常。
(2)使用关键字instanceof。它返回布尔值,告诉我们一个对象是不是某个特定类型的实例。
(3)通过反射机制,查询Class对象获取运行时所需的信息。
类加载的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段,其中验证、准备和解析三个部份统称为链接。
在加载阶段,Java堆中生成一个代表一个类的java.lang.Class对象,该对象记录了该类所有的结构信息,作为方法区这些数据的访问入口。
在初始化阶段,虚拟机规范则是严格规定了有且只有四种情况必须立即对类进行初始化:
(1)遇到new、getstatic、putstatic或invokestatic这四条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这四条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候、以及调用一个类的静态方法的时候。
(2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
(3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
(4)当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个主类。
实例化Class类对象
Class类是反射的源头,该类可以通过3种方式实例化。(1)通过Class类的静态方法Class.forName实例化。(2)通过Object对象的getClass()方法实例化,返回此
Object
的运行时类Class。(3)使用类字面常量实例化Class对象(类名.class),但是它不会自动地初始化该Class对象,因此类中的静态域没有初始化。
static Class<?>
|
返回与带有给定字符串名的类或接口相关联的
Class 对象。 |
static Class<?>
|
forName(String name, boolean initialize, ClassLoader loader) 使用给定的类加载器及是否必须初始化类,返回与带有给定字符串名的类或接口相关联的 Class 对象。 |
取得类的结构信息
通过以上三种方式获取到了Class类,此时我们就可以使用Class类获取类的结构信息,常用方法如下:
int
|
getModifiers()
返回此类或接口以整数编码的 Java 语言修饰符,使用Modifier.toString(int modify)进行转换。
|
boolean |
isEnum()
当且仅当该类声明为源代码中的枚举时返回 true。
|
boolean |
isInterface()
判定指定的 Class 对象是否表示一个接口类型。
|
String
|
getName()
以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 |
String
|
getSimpleName()
返回源代码中给出的底层类的简称。 |
String
|
getCanonicalName()
返回 Java Language Specification 中所定义的底层类的规范化名称。 |
Class<? super T>
|
getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
|
Class<?>[]
|
getInterfaces()
确定此对象所表示的类或接口实现的接口。
|
Constructor<?>[] | getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 |
Constructor<?>[] | getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 |
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 |
Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 |
Method[] | getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 |
Method[] | getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
Method | getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 |
Method | getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
Field[] | getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 |
Field[] | getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 |
Field | getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 |
Field | getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
T | newInstance() 创建此 Class 对象所表示的类的一个新实例。 |
使用Class类可以获取到类的构造方法(Constructor)、方法(Method)和字段属性(Field)。我们就可以实现以下三种操作:
(1)通过Constructor获取构造方法的修饰符、名称、参数类型、抛的异常信息及通过构造方法实例化对象。
(2)通过Method获取方法的修饰符、返回值类型、方法名、参数类型、抛的异常信息及动态调用指定方法。
(3)通过Field获取属性的修饰符、类型、 名称及动态设置属性值。
Constructor常用方法
int
|
getModifiers()
以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。
|
String
|
getName()
以字符串形式返回此构造方法的名称。
|
Class<?>[]
|
getParameterTypes()
按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。
|
Class<?>[]
|
getExceptionTypes()
返回一组表示声明要抛出的异常类型的 Class 对象,这些异常是由此 Constructor 对象表示的底层构造方法抛出的。
|
T
|
newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
|
Method常用方法
int
|
getModifiers()
以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。
|
Class<?>
|
getReturnType()
返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。
|
String
|
getName()
以 String 形式返回此 Method 对象表示的方法名称。
|
Class<?>[]
|
getParameterTypes()
按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。
|
Object
|
invoke(Object obj, Object... args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
|
Field常用方法
int
|
getModifiers()
以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。
|
Class<?>
|
getType()
返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
|
void
|
set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
|
Object
|
get(Object obj)
返回指定对象上此 Field 表示的字段的值。
|