java的rtti中class对象2007-05-29 yycnet.yeah.net yyc译为理解RTTI在Java里如何工作,首先必须了解类型信息在运行期是如何表示的。这时要用到一个名为“Class对象”的特殊形式的对象,其中包含了与类有关的信息(有时也把它叫作“元类”)。事实上,我们要用Class对象创建属于某个类的全部“常规”或“普通”对象。
对于作为程序一部分的每个类,它们都有一个Class对象。换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当地说,是保存在一个完全同名的.class文件中)。在运行期,一旦我们想生成那个类的一个对象,用于执行程序的Java虚拟机(JVM)首先就会检查那个类型的Class对象是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。所以Java程序启动时并不是完全载入的,这一点与许多传统语言都不同。
一旦那个类型的Class对象进入内存,就用它创建那一类型的所有对象。
若这种说法多少让你产生了一点儿迷惑,或者并没有真正理解它,下面这个示范程序或许能提供进一步的帮助:
//: SweetShop.java// Examination of the way the class loader worksclass Candy {static {System.out.println("Loading Candy");}}class Gum {static {System.out.println("Loading Gum");}}class Cookie {static {System.out.println("Loading Cookie");}}public class SweetShop {public static void main(String[] args) {System.out.println("inside main");new Candy();System.out.println("After creating Candy");try {Class.forName("Gum");} catch(ClassNotFoundException e) {e.printStackTrace();}System.out.println("After Class.forName("Gum")");new Cookie();System.out.println("After creating Cookie");}} ///:~
对每个类来说(Candy,Gum和Cookie),它们都有一个static从句,用于在类首次载入时执行。相应的信息会打印出来,告诉我们载入是什么时候进行的。在main()中,对象的创建代码位于打印语句之间,以便侦测载入时间。
特别有趣的一行是:
Class.forName("Gum");
该方法是Class(即全部Class所从属的)的一个static成员。而Class对象和其他任何对象都是类似的,所以能够获取和控制它的一个句柄(装载模块就是干这件事的)。为获得Class的一个句柄,一个办法是使用forName()。它的作用是取得包含了目标类文本名字的一个String(注意拼写和大小写)。最后返回的是一个Class句柄。
该程序在某个JVM中的输出如下:
inside mainLoading CandyAfter creating CandyLoading GumAfter Class.forName("Gum")Loading CookieAfter creating Cookie
可以看到,每个Class只有在它需要的时候才会载入,而static初始化工作是在类载入时执行的。
非常有趣的是,另一个JVM的输出变成了另一个样子:
Loading CandyLoading Cookieinside mainAfter creating CandyLoading GumAfter Class.forName("Gum")After creating Cookie
看来JVM通过检查main()中的代码,已经预测到了对Candy和Cookie的需要,但却看不到Gum,因为它是通过对forName()的一个调用创建的,而不是通过更典型的new调用。尽管这个JVM也达到了我们希望的效果,因为确实会在我们需要之前载入那些类,但却不能肯定这儿展示的行为百分之百正确。
1. 类标记
在Java 1.1中,可以采用第二种方式来产生Class对象的句柄:使用“类标记”。对上述程序来说,看起来就象下面这样:
Gum.class;
这样做不仅更加简单,而且更安全,因为它会在编译期间得到检查。由于它取消了对方法调用的需要,所以执行的效率也会更高。
类标记不仅可以应用于普通类,也可以应用于接口、数组以及基本数据类型。除此以外,针对每种基本数据类型的封装器类,它还存在一个名为TYPE的标准字段。TYPE字段的作用是为相关的基本数据类型产生Class对象的一个句柄,如下所示:
……等价于……
... is equivalent to ...
|
---|
boolean.class
| Boolean.TYPE
|
char.class
| Character.TYPE
|
byte.class
| Byte.TYPE
|
short.class
| Short.TYPE
|
int.class
| Integer.TYPE
|
long.class
| Long.TYPE
|
float.class
| Float.TYPE
|
double.class
| Double.TYPE
|
void.class
| Void.TYPE
|