Java类型信息之RTTI

RTTI(Run Time Type Information)使得你可以在程序运行的时候获取和使用对象的类型信息。先来一个例子:

 1 package re;
 2 import java.util.*;
 3 public class Reflect{    
 4     public static void main(String[] args)throws Exception{
 5         List<shape> sl=Arrays.asList(new circle(),new rectangle(),new square());
 6         for(shape sh:sl){
 7             System.out.println(sh.getClass());    
 8             sh.draw();
 9         }    
10         Father fs=new Son();
11         fs.prin();
12         fs.prin2();
13     }
14 
15 }
16 class Father{
17     public void prin(){
18         System.out.println("this is father");
19     }
20     public void prin2(){
21         System.out.println("this is father");
22     }
23 }
24 class Son extends Father{
25     public void prin(){
26         System.out.println("this is son");
27     }
28 }
29 abstract class shape{
30     void draw(){
31         System.out.println("      "+this+".draw()");        
32     }
33     abstract public String toString();
34 }
35 class circle extends shape{
36     public String toString(){
37         return "circle";
38     }
39 }
40 class rectangle extends shape{
41     public String toString(){
42         return "rectangle";
43     }
44 }
45 class square extends shape{
46     public String toString(){
47         return "square";
48     }
49 }
View Code

这里我们创建的对象的变量类型是shape类型(也就是父类型,也即 father fs=new son(),其中son类继承/实现father),但是在执行draw()方法时,可以获取对象的实际类型的信息,这就是RTTI提供的机制功能,面向对象的多态特性与RTTI机制是分不开的。java的所有类的基类Object中有一个方法: getClass(),java API文档对其作用的描述是“返回此Object的运行时类”,也就是返回创建引用所指向的对象的类,例 father fs=new son(),fs.getClass()返回的是son类,该方法返回类型是Class<T>类型,java API对Class对象的描述是“Class 类的实例表示正在运行的 Java 应用程序中的类和接口”。从而我们可以得知:Class对象关系到我们想要了解的正在运行的对象的类信息。这里对Class对象做一下总结:

Class对象包含了与类有关的信息,《Thinking in Java》中陈述说“Class对象就是用来创建类的所有常规对象的”,也就是我们创建一个对象时,是用这个类的Class对象完成创建工作的。每一个类都有一个Class对象,当我们创建并编译好了一个新类,就会产生一个Class对象,并且该对象被保存在一个同名的.class文件中!当要创建一个类的对象时,类加载器首先会检查这个类的Class对象是否已加载,若没有,类加载器就会根据类名查找.class文件,并将其加载到内存中,然后就用.class中的Class对象去创建这个类的所有对象。

那么,我们可以通过获取一个正在运行的类对象的Class对象,进而通过该Class对象获取对象运行时使用的类型信息了。例如,我们可以获得这个创建这个对象的类中所定义的所有方法,代码如下:

 1 package re;
 2 import java.util.*;
 3 import java.lang.reflect.*;
 4 public class Reflect{    
 5     public static void main(String[] args)throws Exception{
 6         List<shape> sl=Arrays.asList(new circle(),new rectangle(),new square());
 7         for(shape sh:sl){
 8             Class T=sh.getClass();
 9             Method[] me=T.getDeclaredMethods();
10             System.out.println(T);    
11             for(Method m1:me )
12                 System.out.println("      "+m1);    
13             System.out.println("-------------------");    
14         }    
15     }
16 
17 }
18 abstract class shape{
19     void draw(){
20         System.out.println("      "+this+".draw()");        
21     }
22     abstract public String toString();
23 }
24 class circle extends shape{
25     public String toString(){
26         return "circle";
27     }
28 }
29 class rectangle extends shape{
30     public String toString(){
31         return "rectangle";
32     }
33     private void printRectangle(){
34         
35     }
36 }
37 class square extends shape{
38     public String toString(){
39         return "square";
40     }
41 }
View Code

通过运行结果可知,rectangle还有一个私有的printRectangle()方法,当然,我们还可以获取类中定义的成员变量等信息,对于Class对象的知识点先总结到这里。