Java 程序中的许多对象在运行时都会出现两种类型:编译时类型和运行时类型
为了解决这个问题,程序需要在运行时发现对象和类的真实信息。解决该问题有以下两种做法:
- 假设在编译和运行时都完全指定类型的具体信息,在这种情况下,可以先使用 instanceof 运算符进行判断,再利用 强制类型转换将其转换成运行时类型的变量即可。
- 第二种做法是编译时根本无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就必须使用反射。
本文包含:
- 获得 Class 对象
- 从 Class 中获取信息
- Java 8 新增的方法参数反射
1. 获得 Class 对象
每个类被加载之后,系统就会为该类生成一个对应的 Class 对象,通过该 Class 对象就可以访问到 JVM 中的这个类。在 Java 程序中获得 Class 对象通常有如下三种方式。
对于第一种方式和第二种方式都是直接根据类来获得该类的 Class 对象,相比之下,第二种方式有如下两种优势。
2. 从 Class 中获取信息
Class 类提供了大量的实例方法来获取该 Class 对象所对应类的详细信息,Class 类大致包含如下方法,下面每个方法都可能包含多个重载的版本。
下面 4 个方法用于获取 Class 对应类所包含的构造器。
下面 4 个方法用于获取 Class 对应类所包含的方法。
下面 4 个方法用于访问 Class 对应类所包含的成员变量。
如下几个方法用于访问 Class 对应类上所包含的 Annotation。
如下方法用于访问该 Class 对象对应类包含的内部类。
如下方法用于访问 Class 对象对于类所在的外部类。
如下方法用于访问该 Class 对象对应类所实现的接口。
下面方法用于访问该 Class 对象对应类所继承的父类。
如下方法用于获取 Class 对象对应类的修饰符、所在包、类名等基本信息。
此外,Class 对象还调用了如下几个判断方法来判断该类是否为接口、枚举、注解类型等。
上面的多个 getMethod() 方法和 getConstructor() 方法中,都需要传入多个类型为 Class<?>的参数,用于获取指定的方法或指定的构造器。
关于这个参数的作用,假设某个类内包含如下三个 info 方法签名。
这三个同名方法属于重载,它们的方法名相同,但参数列表不同。
如果想指定第二个 info方法,则必须指定方法名为 info ,形参列表为 String.class,在程序中获取该方法使用如下代码:
如果需要获取第三个info 方法,则使用如下代码:
获取构造器时无须传入构造器名—同一个类的所有构造器的名字都是相同的,所以要确定一个构造器只要指定形参列表即可。
3. Java 8 新增的方法参数反射
Java 8 新增了一个 Executable 抽象基类,该对象代表可执行的类成员,该类派生了 Constructor、Method 两个子类。
下面程序示范 Java 8 的条件参数反射功能。
运行该程序,即可看到如下输出: