Java类型信息:RTTI

RTTI
1、RTTI(Run-Time Type Identification):在运行期间对类型进行检验的行为,运行时类型信息使得你可以在程序运行时发现和使用类型信息;
2、RTTI主要有两种实现形式:
(1)传统RTTI:假定在 编译时已经知道所有的类型,
                    编译器在编译时打开和检查.class文件;
(2)反射机制:允许我们在 运行时发现和使用类的信息;
                   .class文件在编译期间不可获取,运行时打开和检查.class;
 
        


Class对象

1、每个类都有一个Class对象,每当编写一个类时会产生一个Class对象(准确地说被保存在一个同名的.class文件中);
生成该类所运行的程序, JVM会使用“类加载器”的子系统
(1)类加载器包含一条加载链,只用一个原生加载器,时JVM实现的一部分;原生加载类加载可信类(包括Java API类),通常不需要额外的类加载器(除非有特殊需求);
(2)所有的类在第一次使用时,动态加载到JVM中,当程序创建一个对类的静态成员的引用时,会加载该类;即java程序在它开始运行之前并未被完全加载;
(3)类加载器首先检查该类的Class对象是都已经加载,如果还未加载,默认的类加载器对根据类名查找.class文件;该类的字节码被加载时,它们会接受检验,以确保其没有被破坏,并且没有包含不良代码;
(4)一旦某个Class对象被载入内存,它就被用来创建该类的所有对象;
(5)对某个实例对象生成Class对象:
Fancytoy toy = new Facncy();
Class<FancyToy> toyclass = toy.forClass();

2、类字面量
(1)Java提供了另外一种方法对Class对象进行引用,即使用类字面量;
如: Class<FancyToy> toyclass = FancyToy.class;
这种做法 更加安全,因为它在编译时会接收检查(因此不需要放置在try块中),同时根除了对forClass()的调用, 更加高效
(2)类字面量不仅可以应用于类,同时还可以应用于接口、数组和基本数据类型;
     对于基本类型的包装类,还有一个相应的TYPE标准字段;

(3) 使用“.class”创建对Class对象的引用时,不会自动初始化该Class对象, 实际有以下三个步骤:
①加载:由类加载器执行,查找字节码(通常在classpath路径),并从相应字节码创建一个Class对象;
②链接:验证类中的字节码,为静态域分配储存空间,在必要时,解析该类创建的对其他类的引用;
③初始化:当该类拥有超类,则对其初始化,执行静态初始化器和静态初始化块;
   初始化被推迟到对静态方法(隐式构造器也被当成静态)或非常数静态域的首次引用时才执行;

3、泛化的Class引用
//创建某Class对象的一个新实例
Class<T> type ;       //Class<T> type = T.class;       //Class<T> type = new Class<T>();
T class = type.newInstance();
//throws InstantionException;  IllegalAccessException;

//创建T父类泛型的Class对象实例的方式:
class Facnytoy extends Toy
Class<Fancytoy> ftclass = Fancytoy.class;
Class<? super Facncytoy> up = ftclass.getSuperclass();
Object obj = up.newInstance();   //此时obj会自动调用Toy的覆盖方法


4、强制转换语法
(1)传统方式
Toy toy = new Toy();
Fancytoy fancytoy = (Fancytoy)toy;
(2)Java SE5引入的cast方式
Toy toy = new Toy();
Class<Fancytoy> fancyClass = Fancytoy.class;
Fancytoy fancytoy = fancyClass.cast(toy);




类型转换前的检查(RTTI在Java中的形式)

1、传统的类型转化形式,如“(shape)”,由RTTI确保类型转换的正确性,如果执行了一个错误的类型转换,会抛出一个ClassCastException异常;
2、代表对象类型的Class对象,通过查询Class对象可以获取运行时所需的信息;(主要解决instanceof无法比较Class对象的限制);
Object obj;
Class<Toy> type = Toy.class;
if(type.isInstance(obj))
     (Toy)obj;
//使用自定义参数列表比较Class对象;
List<Class<? extends Pet>> allTypes = Arrat.asList(Pet.class,Cat.class,Dog.class,.......);
for(Class<? extends Pet> pair : List)
     if(pair.isInstance(obj)){     statements;}
//直接使用Class.isAssignableForm()方法检验某个对象的实例时候为被Class对象的一个实例,或其子类的实例;
Class<Pet> petType = Pet.class;
if(petType.isAssignableForm(obj));     


    

3、RTTI 在Java中特有的第三种方式,关键字instanceof;
if(obj instanceof Toy)
     (Toy)obj;
※Java中的 instanceof 关键字有比较严格的限制:只可以将其与命名类型进行比较,而不能与Class对象进行比较;
※Java中的类型转换检查一般用于检查向下转型,向上转型自动完成;




反射:运行时的类信息

1、反射提供了一种机制:用来检查可用的方法,并返回方法名;Java通过JavaBeans提供了基于构件的编程结构;
2、 Class类和 java.lang.reflect类库(包含:Field,Method,Constructor,都实现了Member接口)一起对反射类库提供了支持;
这些类型在JVM运行时创建,reflect类库类可以通过Class的 getFields()、getMethods()、getConstructors()便利方法获取;
class Man{
     int age = 20;
     String name;
     public Man(String name){     this.name = name;}
     public String speak(String word){     return name+" speak: "+word;}
} 

Class<Man> manType = Man.class;
Constructor con  = manType.getConstructor(String.class);
Man manObject = con.newInsatnce("Alassad");

Mathod med = manType.getMethod("spaek",String.class);
String word = med.invoke("Are you OK?");

Field fdName = manType.getField("name");
Field fdAge = manType.getField("age");
String name =(String)fdName.get(manObject);      // String name = fdAge.getInt(manObject);
fdName.set(manObject, (Object)(new String("I am fine")));  // fdAge.setInt(manObject, 22);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值