摘要:找到字节码并创建一个对象。链接,检验字节码,为字段分配存储空间,解决其对他类的引用。初始化,如果有父类则初始化父类,执行静态初始化器和静态初始化区块直到第一次访问静态成员时初始化才执行。如果成员不是编译时常量由初始化器赋值,也会引起初始化。
有两种形式在运行时获取类型信息:
传统的RTTI
反射
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对象__。获得一个可用的类需要三步
加载,由类加载器完成。找到字节码并创建一个Class对象。
链接,检验字节码,为static字段分配存储空间,解决其对他类的引用。
初始化,如果有父类则初始化父类,执行静态初始化器和静态初始化区块
直到第一次访问静态成员时初始化才执行。
用Class.forName()获得引用则会引起初始化。
如果static final成员是编译时常量,访问这个成员则不会引起初始化。如果static final成员不是编译时常量(由初始化器赋值),也会引起初始化。访问不是final的static成员总会引起链接和初始化,即分配存储和初始化值。
Generic class referencesClass> <=> 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(); ClassChecking before a casthouseType = House.class; House h = houseType.cast(b); h = (House)b; // ... or just do this. } } ///:~
RTTI的三种形态:
传统的类型转换,使用RTTI来确保类型转换时正确,如果不正确会抛出ClassCastException异常
以Class object表示对象的类型。Class对象可以提供很有用的运行时信息。
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 |
一个类默认的构造器和这个类有相同的访问修饰符
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70932.html
摘要:通过运行时类型信息,程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。编程应该尽量面向接口编程,应该对类型信息尽量的少了解二对象看书,书上写得好静态语句块在这个类被加载的时候运行。 一、为什么需要RTTI Run-Time Type Information。通过运行时类型信息,程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。编程应该尽量...
摘要:公司的和作为主要人员创作了其中在年月发布在年月发布。的核心理念是对象都是运动和变化的比如天气。也是对象都是相互关联的比如天气和人的行为。对象的变化都是在同时并行的比如马路上,机动车道上的汽车和非机动车道路上的人都是同时运行的。 前言公司用到rxjava,学习Learning-Rxjava笔记本书源码位置:https://github.com/PacktPubli... 1.A brie...
摘要:扩展单一职责原则又称单一功能原则,面向对象五个基本原则之一。马丁表示此原则是基于汤姆狄马克和的著作中的内聚性原则发展出的。 [解读]Thinking in React 原文:http://facebook.github.io/react/docs/thinking-in-react.html 前言 Thought is the seed of action 这是放置在官方的QUICK ...
摘要:内部类中也可以取得这个外部类对象引用。创建成员内部类对象的时候需要外部类对象。另外在方法中的内部类不能加等权限修饰符,只能加和修饰符。可以在接口内部定义内部类,而且他们即使没有修饰,也会自动变成的。 Thinking in Java捞干货,写笔记 一、成员内部类 1.最基本使用 public class Demo { class Contents{ privat...
摘要:而这可以通过注解办到,在代码中以指令语言的形式化方法来为代码提供更多信息。有注解的说明这个成员变量是一个列名,然后根据注解信息来生成相应的语句。也就是说把注解信息提取了出来。 注解是向代码中添加信息的一种方法,并且在之后还可以使用这些数据就比如这个方法是用来剥香蕉的,但是我们看就是一串代码,我们没办法在代码里写一段指令说我这个程序是用来剥香蕉的,当然除了注释。而这可以通过注解办到,在代...
阅读 1961·2021-09-09 09:33
阅读 1107·2019-08-30 15:43
阅读 2644·2019-08-30 13:45
阅读 3296·2019-08-29 11:00
阅读 845·2019-08-26 14:01
阅读 3558·2019-08-26 13:24
阅读 471·2019-08-26 11:56
阅读 2681·2019-08-26 10:27