类型检查(RTTI与反射机制)转载


                                        类型检查(RTTI与反射机制)


1、类型时类型识别(run-timetype identification,RTTI):当之有一个指向对象的引用时,RTTI可以让你找出这个对象的确切类型。
2、Java运行时识别对象和类的信息,主要有俩种方式:

1).一种是“传统“RTTI,它假定我们在运行时已经知道了所有的类型。

2).另一种是“放射“机制,它允许我们在运行时获得类的信息。

3、Class对象:每个类都有一个Class对象,保存在一个同名的.class文件中,它包含了与类相关的信息。

4、在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class对象是否已经加载,就会根据类名查找.class文件,并将其载入。所以Java并非一开始执行就完全加载的,这一点与许多传统语言都不同。        

5、Class.forName(“类名”)是获得Class引用的一种方法,该方法返回一个Class对象的引用。例如:Class.forName(“MyClass”);

在调用该方法时,若MyClass类被还没加载,则加载MyClass类。

6、类字面常量:另一种获得Class引用的方法,MyClass.class(类名.class)。

此方法,更安全,更高效。

7、类字面常量不仅应用于普通的类,也可以应用于接口、数组以及基本数据类型。

8、RTTI的形式包括:

1).传统的类型转化。如Base类是Subclass类基类。

  1. Base base = new Subclass();  
  2. Subclass sub= (Subclass)base;//(Subclass),由RTTI确定类型转化正确性。在C++中,经典的类型转换“(Subclass)”并不使用RTTI。  

 

2).代表对象的类型的Class对象。同过查询Class对象可以获取运行时所需的信息。

3).RTTI的第三种形式,使用关键字“instanceof”。如:

  1. boolean yesOrNot = (base instanceof Subclass);  

 

若base是Subclass类的实例,yesOrNot就为true

9、instanceof与Class的等价性:

  1. class Base{}  
  2. class Subclass extends Base{};  
  3. public class Test{  
  4.    static void test(Object x){  
  5.       System.out.println("Testing x of type: " + x.getClass());  
  6.       System.out.println("x instanceof Base: " + (x instanceof Base));  
  7.       System.out.println("x instanceof Subclass: " + (x instanceof Subclass));  
  8.       System.out.println("Base.isInstance(x): " + (Base.class.isInstance(x)));  
  9.       System.out.println("Subclass.isInstance(x):" + (Subclass.class.isInstance(x)));  
  10.       System.out.println("x.getClass() == Base.class: " + (x.getClass() == Base.class));  
  11.       System.out.println("x.getClass() == Subclass.class: " + (x.getClass() == Subclass.class));  
  12.       System.out.println("x.getClass().equals(Base.class): " + (x.getClass().equals(Base.class)));  
  13.       System.out.println("x.getClass().equals(Subclass.class): " + (x.getClass().equals(Subclass.class)));  
  14.    }  
  15.    public static void main(String[] args){  
  16.       test(new Base());  
  17.    System.out.println("---------------------------------------------------");  
  18.       test(new Subclass());  
  19.    }  
  20. }  

 

运行结果:

1).instanceof 与 isInstance生成的结果完全一样,equal与==也一样。

2). Instanceof与isInstance保持了类型的概念,它指得是“你是这个类,或者是这个类的派生类吗?”

3).equal与==比较实际的Class对象,没有考虑继承。

10、Java是通过Class对象来实现RTTI机制的,即使我们只是做些诸如类型转换这类的事情。Class类提供的一些方法:

11、RTTI的限制:编译器必须已经知道所有用RTTI来处理的类型。但是,当你从网络连接中获得一串字节,并被告知这些字节代表一个类。可是编译器并不知道这个类的信息。这时你要使用这个类,那么就得使用反射机制

12、RTTI与反射之间的区别:对RTTI来书,编译器在编译时打开和检查.class文件,而对于反射机制,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件的。

13、获取关于类和对象的反射信息在java.lang.reflect库中,它包含了Field、Method以及Constructor类。

1).Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

2). Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

3). Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 

Base类如下:

  1. class Base{  
  2.     private int number = 1;  
  3.     public int otherNum = 100;  
  4.     public Base(){  
  5.           
  6.     }  
  7.     public Base(int number){  
  8.         this.number = number;  
  9.     }  
  10.     public void func(){  
  11.         number++;  
  12.     }  
  13.     public void otherFunc(){  
  14.         otherNum--;  
  15.     }  
  16. }  
Test:
  1. public class Test{  
  2.     public static void main(String[] args){  
  3.         Constructor[] constructors = null;  
  4.         Method[] methods = null;  
  5.         Field[] fields = null;  
  6.         try {  
  7.             Class c = Class.forName("Base");  
  8.             constructors = c.getConstructors();//公有构造方法。  
  9.             methods = c.getMethods();//公有方法。  
  10.             fields = c.getFields();//公有字段。  
  11.         } catch (ClassNotFoundException e) {  
  12.             e.printStackTrace();  
  13.         } catch (SecurityException e) {  
  14.             e.printStackTrace();  
  15.         }  
  16.         System.out.println("Base含有的公有构造方法:");  
  17.         for(int i = 0; i < constructors.length; i++){  
  18.             System.out.println(constructors[i].getName());  
  19.         }  
  20.         System.out.println("Base含有的公有方法(有些是从Oject继承的):");  
  21.         for(int i = 0; i < methods.length; i++){  
  22.             System.out.println(methods[i].getName());     
  23.         }  
  24.         System.out.println("Base含有的公有字段:");  
  25.         for(int i = 0; i < fields.length; i++){  
  26.             System.out.println(fields[i].getName());          
  27.         }  
  28.     }  
  29. }  
运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值