Java 在运行期间查找对象和类信息。这主要采取两种形式:一种是“传统”RTTI ,它假定我们已在编译和运行期拥有所有类型;另一种是Java1.1 特有的“反射”机制 ,利用它可在运行期独立查找类信息
class 对象
对于作为程序一部分的每个类,它们都有一个Class 对象。换言之,每次写一个新类时,同时也会创建一个Class 对象(更恰当地说,是保存在一个完全同名的.class 文件中)。
在运行期,一旦我们想生成那个类的一个对象,用于执行程序的Java 虚拟机(JVM)首先就会检查那个类型的Class 对象是否已经载入。若尚未载入,JVM 就会查找同名的.class 文件,并将其载入。所以Java 程序启动时并不是完全载入的
Class.forName 该方法是Class(即全部Class 所从属的)的一个static 成员,返回的是一个Class 句柄。每个Class 只有在它需要的时候才会载入,而static 初始化工作是在类载入时执行的
(1)RTTI 在Java 中存在三种形式
1 instanceof
关键字instanceof 告诉我们对象是不是一个特定类型的实例(Instance 即“实例”)。它会返回一个布尔值,以便以问题的形式使用
if(x instanceof Dog)
((Dog)x).bark();
2 isInstance
Java 1.1 为Class 类添加了isInstance 方法。利用它可以动态调用instanceof 运算符。
3 getClass
为了取得Class 句柄,可调用属于Object 根类一部分的一个方法:getClass()。它的作用是返回一个特定的Class 句柄,用来表示对象的实际类型。getInterfaces() 方法会返回Class 对象的一个数组,用于表示包含在Class 对象内的接口。也可以用getSuperclass()查询该对象的直接基础类是什么
(2)反射:运行期类信息
通过“反射”同一个未知类型的对象打交道时,JVM 只是简单地检查那个对象,并调查它从属于哪个特定的类。但在这之后,在我们做其他任何事情之前,Class 对象必须载入。因此,用于那种特定类型的.class 文件必须能由JVM 调用
RTTI 和“反射”之间唯一的区别就是对RTTI 来说,编译器会在编译期打开和检查.class 文件。换句话说,我们可以用“普通”方式调用一个对象的所有方法;但对“反射”来说,.class 文件在编译期间是不可使用的,而是由运行期环境打开和检查。
Class 方法getMethods()和getConstructors()可以分别返回Method 和Constructor 的一个数组