Thinking in Java学习笔记——Type Information

发布时间:2019-11-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Thinking in Java学习笔记——Type Information脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

有两种形式在运行时获取类型信息:

  1. 传统的RTTI
  2. 反射

Class对象

  • 运行时的类型信息是通过Class对象表现的,它包含了类的信息。所有“普通的”对象都是通过Class对象创建的。Java通过Class对象实现RTTI。
  • 在你的程序中每个类都对应一个Class对象。每次编写并编译一个新的类时都会创建一个相应的Class对象,并且以.class文件储存起来。JVM用class loader子系统创建对象。
  • JVM有一个原生的class loader用来加载“可信类”,包括JAVA API中的类。你也可以实现自己的带有特殊目的的class loader并与原生的串联起来。
  • 在一个类第一次被访问static成员时,这个类则被加载到JVM。构造函数也是静态的,所以用new创建对象时也算访问了static成员。因此Java程序运行前并不是完全加载了。
  • class loader先检查类型的Class对象是否加载了,如果没加载,class loader会找到.class文件(其他的class loader可能会从别处加载二进制码,比如从数据库)。字节被加载之后会被验证一下有没有损坏或者有没有不安全的代码。
  • Class对象被加载到内存之后,将被用来创建这个类型的所有对象。
  • 所有Class对象都属于Class类,和其他类一样可以使用引用操作Class对象。一种获得Class对象的方法是调用静态的forName()方法,这个方法接收一个字符串类型,是类的名字,需要使用包括报名的全名。如果找不到.class文件,会抛出一个ClassNotFoundException
  • 在运行时,使用类型信息之前要先获取Class对象。Class.forName()是比较方便的做法。如果已经有一个这个类型的对象了,可以调用对象getClass()方法,这个方法是在Object里定义的。

Class lITerals

除了forName()外,Java还提供一种获得Class对象引用的方法,比如Toy.class。这种方法更简洁和更安全,因为这种方法的类型在编译时就会被检查。

基本类型的包装类有一个标准字段TYPE,提供了基本类型的Class对象,例如:boolean.class <=> Boolean.TYPE

__使用.class获得Class对象引用不会初始化Class对象__。获得一个可用的类需要三步

  1. 加载,由类加载器完成。找到字节码并创建一个Class对象。
  2. 链接检验字节码,为static字段分配存储空间,解决其对他类的引用。
  3. 初始化,如果有父类则初始化父类,执行静态初始化器和静态初始化区块

直到第一次访问静态成员时初始化才执行。

Class.forName()获得引用则会引起初始化。

如果static final成员是编译时常量,访问这个成员则不会引起初始化。如果static final成员不是编译时常量(由初始化器赋值),也会引起初始化。访问不是final的static成员总会引起链接和初始化,即分配存储和初始化值。

Generic class references

Class<?> <=> Class

使用generic语法可以让你在编译时就发现类型不对的错误。只用Class的话,如果犯了错误到运行时才会发现。

New cast syntax

//: typeinfo/ClassCasts.java class Building {} class House extends Building {}  public class ClassCasts {       public static void main(String[] args) {         Building b = new House();         Class<House> houseType = House.class;         House h = houseType.cast(b);         h = (House)b; // ... or just do this.       } } ///:~

Checking before a cast

RTTI的三种形态:

  1. 传统的类型转换,使用RTTI来确保类型转换时正确,如果不正确会抛出ClassCastException异常
  2. Class object表示对象的类型。Class对象可以提供很有用的运行时信息。
  3. instanceof,检验对象是不是某类型。(动态Class.islnstance())

反射

RTTI可以提供类型信息,但是如果在编译时并不知道对象所属类的信息(比如从硬盘或网络读取的字节所组成的类),则无法使用RTTI。

Class类和java.lang.reflect中的Field, Method, and Constructor(实现了Member接口)一起支持了反射的概念。在运行时,JVM会创建这些类型的对象来表示未知类的成员。

使用反射前提是JVM可以找到未知类型的.class文件(从硬盘中的文件或者网络)。

  • RTTI在编译时,由编译器打开和检查.class文件。
  • 在反射机制中,.class在编译时是不可用的,.class是由运行环境在运行时打开和检查的。

接口和类型信息

利用反射可以访问对象的方法和成员变量,不论访问修饰符是什么。但是反射不能修改final的变量,在运行时试图修改final字段不会报错,但是实际上修改并没有生效

概念

class type .class文件 Class Class object Class reference
java中的类 类型,对应于一个类,每个类都是一个类型 用来储存Class对象,程序中编写的每个类,都会被编译成一个.class文件 一种叫“Class”的类 Class类的一个实例,这个类由.class文件而来,负责创建它所表示的类的实例 Class object的引用,包括了这个类的statics

其他小知识

  • 一个类默认的构造器和这个类有相同的访问修饰符

脚本宝典总结

以上是脚本宝典为你收集整理的Thinking in Java学习笔记——Type Information全部内容,希望文章能够帮你解决Thinking in Java学习笔记——Type Information所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。