第11章 运行期类型鉴定
Java提供两种方法:一种是”传统”RTTI,它的限制是:类型必须是在编译期间已知的;另一种是Java1.1特有的”反射”机制,利用它可在运行期独立查找类信息。
RTTI
RTTI技术用它查询继承类句柄的准确类型。包括从interface、abstract或者普通类继承的类型。
每个类都有一个static从句,在类首次载入时执行,可以做一些初始化工作。
class Candy {
static {
System.out.println(”Loading Candy”);
}
}
Class对象
每个类都有一个Class对象。Class对象保存在同名的.class文件中。在运行期,一旦想生成类的对象,JVM首先检查类型的Class对象是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。而一旦那个类型的Class对象进入内存,就用它创建那一类型的所有对象。
Class.forName(”Gum”)
为获得Class的一个句柄,一个办法是使用forName(),比如:Class.forName(”Gum”); 它用RTTI确保造型的正确性,并在遇到一个失败的造型后产生一个ClassCastException违例。
类标记Gum.class
类标记更简单,更安全。它会在编译期间得到检查,不会象Class.forName()那样”掷”出违例。而由于它取消了对方法调用的需要,所以执行的效率也会更高。
类标记不仅可以应用于普通类,也可以应用于接口、数组以及基本数据类型。除此以外,针对每种基本数据类型的封装器类,它还存在一个名为TYPE的标准字段,可以为相关的基本数据类型产生Class对象的一个句柄,比如Boolean.TYPE就相当于boolean.class。
造型前检查
1、instanceof 表示对象是不是特定类型的实例。它返回一个布尔值,如:
if(x instanceof Dog)
((Dog)x).bark();
这种需要制定类名Dog的方法叫做静态调用。
2、动态isInstance方法
Java 1.1为Class类添加了isInstance方法。利用它可以动态调用instanceof运算符。如
Object o = pets.elementAt(i); # pets里包括类的Instance
petTypes[j].isInstance(o)) # petTypes里包括类对象
RTTI语法
Java用Class对象实现自己的RTTI功能。
Class提供了几个有趣且较为有用的方法,Class.getInterfaces(); getSuperclass(); newInstance(); toString() = “class c11.petcount2.Pet”; getName(); isInterface();
注意,用newInstance()创建的类必须有一个默认构建器。没有办法用newInstance()创建拥有非默认构建器的对象,所以在Java 1.0中可能存在一些限制。然而,Java 1.1的”反射”API(下一节讨论)却允许我们动态地使用类里的任何构建器。
Class_Instance.getClass();
反射:运行期类信息
假若得到的是不在自己程序空间内的对象的句柄,这时RTTI就无法工作了。比如基于组件的程序设计和远程方法调用”(RMI)。但我们很少需要直接使用反射工具。
新增库:java.lang.reflect提供了针对Field,Method以及Constructor的三个类。这些类型的对象都是JVM在运行期创建的,用于代表未知类里对应的成员。这样便可用构建器创建新对象,用get()和set()方法读取和修改与Field对象关联的字段,以及用invoke()方法调用与Method对象关联的方法。我们可调用方法getFields(),getMethods(),getConstructors(),分别返回用于表示字段、方法以及构建器的对象数组,使匿名对象的类信息在运行期被完整的揭露出来
StreamTokenizer
Technorati : Java