RTTI与反射

来源:互联网 发布:超氧换血疗法 知乎 编辑:程序博客网 时间:2024/05/23 13:24
严格的说,反射也是一种形式的RTTI,不过,一般的文档资料中把RTTI和反射分开,因为一般的,大家认为RTTI指的是传统的RTTI,通过继承和多态来实现,在运行时通过调用超类的方法来实现具体的功能(超类会自动实例化为子类,或使用instance of)。
传统的RTTI有3种实现方式:
1.传统类型转换 String string = (String) s;
2.Class对象(用了Class对象,不代表就是反射,如果只是用Class对象cast成指定的类,那就还是传统的RTTI)
3.instanceof或isInstance()
传统的RTTI与反射最主要的区别,在于RTTI在编译期需要.class文件,而反射不需要。传统的RTTI使用转型或Instance形式实现,但都需要指定要转型的类型,比如:

public void rtti(Object obj){
    Toy toy = Toy(obj);
}
注意其中的obj虽然是被转型了,但在编译期,就需要知道要转成的类型Toy,也就是需要Toy的.class文件。

相对的,反射完全在运行时在通过Class类来确定类型,不需要提前加载Toy的.class文件。


Java中有时候在编译器为程序生成代码很久之后才会出现要处理的那个类,那么这个时候怎么才能处理这个类呢,即在编译的时候根本无法获知这个对象所属的类。答案就是利用Java的反射机制。Java的反射与RTTI的区别就在于编译时不需要知道任何事情,匿名对象的信息在运行时确定下来就可以


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class ShowMethods {    
  2.     private static String usage=    
  3.             "usage"+    
  4.     "showMethods qualified.class.name\n"+    
  5.                     "To show all methods in class or:\n"+    
  6.     "showMethods qualified.class.name word\n"+    
  7.                     "To search for methods involving 'word'";    
  8.     private static Pattern p=Pattern.compile("\\w+\\.");    
  9.     
  10.     /**  
  11.      * @param args  
  12.      */    
  13.     public static void main(String[] args) {    
  14.         // TODO Auto-generated method stub    
  15.     if(args.length<1){    
  16.         System.out.println(usage);    
  17.         System.exit(0);    
  18.     }    
  19.     int lines=0;    
  20.     try{    
  21.         Class<?> c=Class.forName(args[0]);    
  22.         Method[] methods=c.getMethods();    
  23.         Constructor[] ctors=c.getConstructors();    
  24.         if(args.length==1){    
  25.             for(Method method:methods)    
  26.                 System.out.println(p.matcher(method.toString()));    
  27.             for(Constructor cotr:ctors)    
  28.                 System.out.println(p.matcher(cotr.toString()));    
  29.             lines=methods.length+ctors.length;    
  30.         }else{    
  31.             for(Method method:methods)    
  32.                 if(method.toString().indexOf(args[1])!=-1){    
  33.                 System.out.println(method.toString());    
  34.             lines++;    
  35.                 }    
  36.               }    
  37.             for(Constructor ctor:ctors)    
  38.                 if(ctor.toString().indexOf(args[1])!=-1){    
  39.                     System.out.println(p.matcher(ctor.toString()).replaceAll(""));    
  40.                     lines++;    
  41.                 }    
  42.     }catch(ClassNotFoundException e){    
  43.         System.out.println("No such class"+e);    
  44.     }    
  45.     }    

在这个类编译时:javac ShowMethods.java  
//这个时候完全不知道
Class<?> c=Class.forName(args[0]);  
中的args[0]的内容是什么。
运行时:Java ShowMethods ShowMethods
此时第二个ShowMethods为参数传递进去,即运行时才获得了类型信息。这便是反射

Class类是支持范型的:
Class<Integer> c = int.class;
Class范型的作用是可以得到编译器的支持,比如类型检查:
Class<Interger> c = int.class;
除了类型检查,Class范型的new Instance会返回相应类型的对象,不仅仅是个简单的Object:
Class c = int.class;
Class<Integer> cc = int.class;
Object o = c.newInstance();
Integer i = cc.newInstance();

0 0
原创粉丝点击