第十四章 类型信息:RTTI(Run-Time Type Information)/反射
- RTTI:有三种形式
- 传统的类型转换,如向上转型,由RTTI确保转换的正确性,如果执行一个错误的转化,就会抛出ClassCastException
- 代表对象的类型的Class对象,通过查询Class对象可以获取运行时所需的信息
- 关键字instanceof,返回一个bool值,告诉我们对象是不是某个特定类型的实例
- Class对象
- class对象就是用来创建类的所有的“常规”对象的
- Java使用Class对象来执行其RTTI
- 每一类都是一个Class对象,并且存在.class中,即字节码,JVM会使用"类加载器"的子系统
- 所有的类都是在第一次使用时,动态加载到JVM中,static初始化是在类加载的时候进行的
- Class.forName():一个static成员,取得Class对象的引用的一种方法,传参时必须使用全限定名
- 如果已经拥有了一个感兴趣的类型的对象,可以通过getClass()方法来获取Class引用,这是Object的方法
- 类字面常量
- java还提供了另一种方法来生成对class对象的引用,即使用类字面常量,xxx.class
- 可以运用于类,接口,数组即基本数据类型
- 对于基本数据类型的包装类型,可以用于标准字段TYPE,TYPE是一个引用,指向对应的额基本数据类型的Class对象
- 注意:当使用.class来创建Class对象的引用时,不会自动初始化该Class对象,会通过三步
- 加载:由类加载器执行。查找字节码(通常由classpath指定路径),并从这些字节码中创建一个Class对象
- 链接:验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用
- 初始化:如果该类具有超类,对其进行初始化,执行静态初始化器和静态初始化块
- 如果一个static final值是"编译器常量",那么这个值不需要对类初始化就可以被读取,但是如果一个域设置为static和final,还不足以确保这种行为;如果一个域是static并不是final的,那么在对它访问时,总是要求在它被读取之前,进行连接(为这个域分配存储空间)和初始化(初始化该存储空间)
- Integer继承Number,但是Integer Class不是Number CLass对象的子类
- 由于5的原因,所以出现? extends Number来创建一个域
- 注解@SuppressWarnings不能直接置于静态初始化子句上
- instanceof保持了类型的概念,它指的是“你是这个类吗,或者你是这个类的派生类吗?”而如果用==/equals比较实际的Class对象,就没有考虑继承——它或者是这个确切的类型或者不是
- 反射:运行时的类信息
- 使用RTTI时要求类型必须在编译时已知,而反射就是为了解决这个条件的
- 和RTTI的区别:对于RTTI来说,编译器在编译时打开和检查.class文件,而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件
- 支持序列号和javaBean
- 未完待续~