Java类型信息(RTTI和反射)
要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人!
最近在学习反射,为了更好地理解反射,就去查各种资料学习了java类型信息。
目录
- 前言
- java类的加载和初始化
- Class对象
- java类型信息
一、前言
在了解java类型信息前,需要先了解我们编写的类在Java中是如何加载的,以及Class类的基本概念和作用,以方便我们更好理解Java类型信息。
二、类的加载和初始化
2.1 类的加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类的初始化。
- 加载
- 就是指class文件读入内存,并为之创建一个Class对象(下文会详细介绍)
- 任何类被使用时系统都会为之建立一个Class对象。
- 连接
- 验证 是否有正确的内部结构,并和其他类协调一致
- 准备 负责为类的静态成员分配内存,并设置默认初始化值
- 解析 对类中的接口、类、方法、变量的符号引用进行解析并定位,解析成直接引用(符号引用就是编码时用字符串表示某个变量、接口的位置,直接引用就是根据符号引用翻译出来的地址)
- 初始化
- 初始化Java代码和静态Java代码块,即在内存中建立java内存模型
2.2 类的加载时机
- 第一次创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方法强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个类
2.3类加载器
- Bootstrap ClassLoader 根类加载器
- Extension ClassLoader 扩展类加载器
- System ClassLoader 系统类加载器
- Bootstrap ClassLoader 根类加载器
- 也被称为引导类的加载器,负责Java核心类的加载
- 比如System String等,在JDK中JRE的lib目录下rt.jar文件中
- 也被称为引导类的加载器,负责Java核心类的加载
- Extension ClassLoader扩展类加载器
- 负责JRE的扩展目录中jar包的加载
- 在JDK中JRE的lib目录下ext目录
- 负责JRE的扩展目录中jar包的加载
- System ClassLoader系统类加载器
- 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类型
2.4 双亲委派模型
类加载器Java类如同其他的Java类一样,也是要由类加载器来加载的。除了启动类根类加载器每个类都有其父类加载器(父子关系有组合(不是继承)来实现)。
所谓双亲委派模型是指每次收到类加载请求时,先将请求委派给父类加载器完成(所有加载请求最终会委派到顶层的Bootstrap Class Loader加载器中),如果父类加载器无法完成这个加载(该加载器的搜索范围没有找到对应的类),子类尝试自己加载。

双亲委派好处
- 避免同一个类被加载多次
- 每个加载 器只能加载自己范围内的类
三、Class类
Class类封装一个对象和接口的运行时的状态(即在这个类的对象中记录每个对象所属的类,保存类的类型信息)。操作类对象在使用前会经历上文所说的加载过程(加载、裂解和初始化),并为之创建一个Class类的对象---Class对象,存放在操作类的.class文件中。这个Class类对象与操作类class是一一对应的,即当一个操作类被加载后,就不会重复加载。而通过该class对象,就可以访问对应的class。我们可以把Class理解为一个类的标识对象,它相当于是一个类的铭牌。拿到一个Class,我们就可以找到对应的类。
注意,Class类没有公有(public)构造方法,因此不能显式地声明一个Class对象,只在类加载时创建。
从Class对象中可以获得的信息:
- 获取到class所包含的构造器
- 获取到class所包含的方法
- 获取到class所包含的成员变量
- 获取到class所包含的Annotation
另外,网上很多帖子说,一旦某个操作类的Class对象被载入内存,就用它来产生该操作类的所有对象!
获取Class对象的三种方式:
- 调用Object类的getClass()方法来得到Class对象,如:
Dog dog;
Class class = dog.getClass();
- 使用Class类中的静态方法forName(string)获得与参数string对象的类的Class对象。例如
Class class = Class.forName("Dog");
- 任何类都具备一个静态的属性(class属性),可引用这个属性获得对应的Class对象,如:
Class class = Dog.class;
Class类常用的方法:
- getName()
- o 返回由 类对象表示的实体(类,接口,数组类,原始类型或空白)的名称,作为 String 。
- newInstance()
- o 创建由此 类对象表示的类的新实例。
- getClassLoader
- o 返回该类的类加载器
四、Java类型信息
我们知道,我们的程序在运行时,某一个操作类可以回被实例化多个对象,一个程序也可能拥有若干个不同操作类的多个对象,那么Java如何在运行时识别对象所属和类的信息的呢?答案是运行时类型信息(Run-Time Type Identification),RTTI使得你可以在程序运行时发现和使用类型信息。
一、RTTI概要
- 类型信息RTTI:即对象和类的信息,例如类的名字、继承的基类、实现的接口等。
- 类型信息的作用:程序员可以在程序运行时发现和使用类型信息。
- RTTI真正含义:运行时,识别一个对象的类型。
二、RTTI的实现方式
- 传统RTTI:即在编译时已知道了所有的类型
- 反射机制:在程序运行时发现和使用类的信息
三、传统RTTI的使用
abstract class Shapes{
void draw(){
System.out.println(this+".draw()");
}
abstract public String toString();
}
class Circle extends Shapes{
public String toString(){
return "Circle";
}
}
class Triangle extends Shapes{
public String toString(){
return "Triangle";
}
}
class Square extends Shapes{
public String toString(){
return "Square";
}
}
class Test{
public static List<Shapes>getList(){
List<Shapes> list_aShapes = Arrays.asList(new Circle,new Square,new Triangle);
}
}
public class Shape{
public static void main(String args[]){
List<Shapes> list_aShapes = Test.getList();
for(Shapes shape:list_aShapes){
shape.draw();
}
}
}
运行结果:Circle.draw()
Square.draw()
Triangle.draw()
结果分析:
上面代码中,shape对象只是一个泛化引用,显然一开始系统并不知道泛华引用的确切类型,我们希望使用的是shape对象对应的确切类型,这是,就需要系统使用RTTI。上例,只是打印出泛化引用的所有类型。进一步解析,Circle,Square,Triangle三个类都继承了抽象类Shape,现有一个List<Shape>的数组,存的是Circle,Square.Triangle的对象,当你拿出一个对象时,你只知道她是Shape类,但不知道它的具体类型。使用RTTI,可以查询到某个shape引用所指向对象的具体类型。
四、反射机制
java反射的官方介绍是 反射机制是在运行中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
反射机制能做什么?
- 在运行时判断任意一个类所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
其实,我们在学习框架时能够发现反射的广泛应用,通过反射和一个未知类型的对象打交道,Class类和java.lang.reflection类库一起对反射作技术支撑,该类库包含Field,Method和Constructor类,这些类的对象由JVM启动时创建,用以表示未知类里对应的成员。
关于反射的详细内容之后的文章会介绍!
五、传统RTTI和反射的共同点和区别
区别:
一、如果该类在编译前就已知。也就是该类在classPath路径下。这就是传统RTTI。
二、如果该类编译器未知,也就是在程序运行时才知道的。这就是反射
所以RTTI和反射的本质区别只是检查一个类的.class文件的时机不同,反射:.class 文件是在编译时不可获得的,所以在运行时打开和检查未知类的.class文件从而变已知。RTTI: .class 文件是在编译时打开和检查。
相同点:都是基于Class类来执行的,都可以获取类的类型信息。
六、总述
其实大家会发现,相比于反射,我们基本不会接触到传统RTTI机制,这是为何呢?其实它的名字已经给出了答案,这是一个机制---传统RTTI机制,其实在Java很多地方都依赖于这个机制来实现,比如说多态(当我们把子类对象的引用赋给父类对象的情况时,需要使用RTTI去识别该对象所属的类),所以说这并不是可有可有的。我们也可以在网上的很多文章看到,很多文章都是把RTTI分为传统RTTI和反射,以阐述java类型信息的详情,这样我们即可以很好地学习反射,也搞清楚了Java在运行时对于对象的识别方法。
Java类型信息(RTTI和反射)的更多相关文章
- Thinking in Java -- 类型信息RTTI
Thinking in Java – 类型信息 个人感觉 java 中的比較难的部分了,在看了些netty源代码发现事实上这块很实用. 这章重点是RTTI和反射.先说下自己的理解 RTTI是执行时识别 ...
- JAVA类型信息——反射机制
JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...
- Java基础 -- 深入理解Java类型信息(Class对象)与反射机制
一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...
- JAVA类型信息——Class对象
JAVA类型信息——Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...
- Java 类型信息
<Thinking in Java 4th>第14章 类型信息 运行时类型信息(Run-Time Type Identification)使得你可以在程序运行时发现和使用类型信息. 14. ...
- Java类型信息
一.引言 最近在阅读<Java编程思想>,学习一下java类型信息,现在做一下总结.Java如何让我们在运行时识别对象和类的信息的.主要有两种方式:一种是传统的“RTTI”,它假定我们在编 ...
- JAVA类型信息——Class对象(转载)
JAVA类型信息--Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...
- 【Java核心技术】类型信息(Class对象 反射 动态代理)
1 Class对象 理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息.Class对象就是用来创建所有“常规”对象的,J ...
- Java 类型信息详解和反射机制
本文部分摘自 On Java 8 RTTI RTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限 ...
随机推荐
- 44 (OC)* 野指针、空指针
一: 空指针 : 没有存储任何内存地址的指针就称为空指针(NULL指针). 被赋值为nil的指针,在没有被具体初始化之前,为nil.nil.Nil.NULL.NSNULL的含义和区别 nil:OC中的 ...
- Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析
在上一篇文章Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例中我们谈到了properties,settings,envir ...
- 网关鉴权后下游统一filter获取用户信息
1. 场景描述 最近有点忙,在弄微服务nacos+springcloud gateway这块工作,以前只是简单应用,这次因为要对接10几个系统或者平台,还的鉴权,等后续稍微闲点了,把这块东西总结下. ...
- Jmeter BeanShell 执行多次问题,每发送一次请求执行一次BeanShell问题
前言:(此问题耗时半天) 提供解决思路的博主又有新问题了. 如图所示,写了一个BeanShell从文件中去获取值之后给测试计划的变量赋值. 问题来了,当禁用b的情况下,a只执行一次.当启用b请求的情况 ...
- 从一道面试题深入了解java虚拟机内存结构
记得刚大学毕业时,为了应付面试,疯狂的在网上刷JAVA的面试题,很多都靠死记硬背.其中有道面试题,给我的印象非常之深刻,有个大厂的面试官,顺着这道题目,一直往下问,问到java虚拟机的知识,最后把我给 ...
- ThinkPHP框架快速开发网站
使用ThinkPHP框架快速搭建网站 这一周一直忙于做实验室的网站,基本功能算是完成了.比较有收获的是大概了解了ThinkPHP框架.写一些东西留作纪念吧.如果对于同样是Web方面新手的你有一丝丝帮助 ...
- 人人都是 API 设计师:我对 RESTful API、GraphQL、RPC API 的思考
原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. 有一段时间没怎么写文章了,今天提笔写一 ...
- B/S 端 WebGL 3D 游戏机教程
前言 摘要:2D 的俄罗斯方块已经被人玩烂了,突发奇想就做了个 3D 的游戏机,用来玩俄罗斯方块...实现的基本想法是先在 2D 上实现俄罗斯方块小游戏,然后使用 3D 建模功能创建一个 3D 街机模 ...
- 浅拷贝&深拷贝的对比
js中两种数据类型 浅拷贝:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的 ...
- iOS渠道分包2种模式之包内注入文件分包
解决问题:商业模式中会存在这样的形式1款app需要不同的运用团队(工会)去分包推广,谁推广的包下载的人数都会在服务器记录,不同渠道的标示唯一来区分. iOS渠道分包模式有两种 一.IDFA模式 IDF ...