为领略RTTI在Java里如何事情,首先必需相识范例信息在运行期是如何暗示的。这时要用到一个名为“Class工具”的非凡形式的工具,个中包括了与类有关的信息(有时也把它叫作“元类”)。事实上,我们要用Class工具建设属于某个类的全部“通例”或“普通”工具。
对付作为措施一部门的每个类,它们都有一个Class工具。换言之,每次写一个新类时,同时也会建设一个Class工具(更恰内地说,是生存在一个完全同名的.class文件中)。在运行期,一旦我们想生成谁人类的一个工具,用于执行措施的Java虚拟机(JVM)首先就会查抄谁人范例的Class工具是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。所以Java措施启动时并不是完全载入的,这一点与很多传统语言都差异。
一旦谁人范例的Class工具进入内存,就用它建设那一范例的所有工具。
若这种说法几多让你发生了一点儿疑惑,可能并没有真正领略它,下面这个示范措施或者能提供进一步的辅佐:
//: SweetShop.java // Examination of the way the class loader works class 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 main Loading Candy After creating Candy Loading Gum After Class.forName("Gum") Loading Cookie After creating Cookie
可以看到,每个Class只有在它需要的时候才会载入,而static初始化事情是在类载入时执行的。
很是有趣的是,另一个JVM的输出酿成了另一个样子:
Loading Candy Loading Cookie inside main After creating Candy Loading Gum After 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 |