Java反射机制Reflection
Java反射机制
了解Java的反射机制,首先要从RTTI开始。
文章的一开头就开始装逼了,RTTI是个什么东西。RTTI英文全称:Run-Time Type Information,望文生义,RTTI是运行时类型信息。
什么是RTTI,有什么作用,编程时会用到吗?这个问题先放在这里,等会再解答。
1, .class文件
学过一点点Java的人,都知道Java文件在编译之后变成了class文件。问题又来了,class文件是什么?肯定有人回答:Class文件就是一个编译后的文件,就像C/C++的.c和.cpp文件编译之后编程了.o,还需要解释吗?要,必须要。
先来一张class文件的文件格式示意图。
没看懂?必然看不懂,先简单介绍一下Class文件。
Class文件从文件类型上是二进制文件,问题又来了,什么是二进制文件?二进制文件就是机器能读懂的语言,自从冯诺依曼的原型机出世,所有的计算机作为它的后代就只认识1和0这两个数字。二进制文件就是一堆0和1。Class文件就是由一堆0和1堆起来的。但是,无规矩不成方圆,这些0和1是按照某种严格的规则放置在对应的位置上。JVM作为Java的运行环境,是规则的制定者和解读者(尽管是Java的开发者们制定的,我们可以简单地认为JVM做了这些事情,至少是开发者们让JVM这么干的)。JVM按照规则来解读0和1序列,然后告诉计算机如何去执行我们的程序所表达的意愿。
但是,Class文件的结构不像XML那些描述型语言那样松散和自由,它的定义是非常严格的,条件也非常的苛刻。Class文件没有任何的分割符号,哪怕是一个空格一个回车(关于回车为什么叫做回车,点击这里)。
在图中Class文件的几个部分,Header,Constant pool...等,这些数据项无论是顺序还是数量都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何都被非常苛刻地限制,不允许改变。然后,你会看到Class attributes在class文件的最后,应该用过Java反编译器吧,有没有注意过Java反编译器反编译的class文件方法在上面,属性都在下面,就是这个原因。
这篇博客讲解的很详细,http://blog.csdn.net/dc_726/article/details/7944154。
文件的开头是Header,,这段十六进制码表明了JDK的版本号,所以你把JDK1.7的class文件放在JDK1.6的环境下就不能运行,向下兼容。
2, Class类
扯得有点远了。回到正题。
Java被编译后,生成了.class文件,JVM此时就要去解读.class文件。当程序主动去使用某个类时,如果这个类还没有被加载到内存中,JVM会通过三个步骤对类进行初始化:
1.加载:由类加载器执行,该步骤查找字节码,并从这些字节码中创建一个Class对象
2.链接:在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用。
3.初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块。
如以上三步,一个.class文件被融入到程序中供其调用。第一个步骤中,查找字节码并生成一个Class对象,在Java中,如Thinking in Java中提到的,一切皆是对象。被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是java.lang.Class。
这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类(所谓的动态是按照动态语言的定义——在程序运行时改变其结构:心得函数可以被引进,已有的函数可以被删除等在结构上的变化)。 由此,可以看出反射机制使得Java语言多么灵活。
3,Class类与反射机制
Class类的概念尽管很抽象,但是无疑,它是反射机制的起源,是Java语言中一个精巧美妙地设计。
介绍完.class文件是怎么回事,又简单说明了.class和Class之间的关系,然后要看一下Class类的官方描述。
官方文档是最权威的,先来看一下Class类中的API是如何描述Class类的。下面是翻译后的中文文档的描述:
Class类的实例表示正在运行的Java应用程序的类和接口。枚举是一种类,注释(注解)是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的Java类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。Class没有公用构造方法。Class对象是在加载类时由JVM以及通过调用类加载器中的defineClass方法自动构造的。
看完这个描述,并结合上面提到的三个步骤,应该会有更好的理解。
4,反射机制的定义和应用
在深入到反射机制之前,先探析一下反射机制的定义和应用。反射机制定义:Java反射机制是在运行状态时,对于任意一个类,都能够直到这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
我们不禁会想,得到这些属性和方法并且去改变它们有什么用?觉得反射机制仿佛很遥远,但是作为一个全职程序员,除了假期和双休日,你几乎每天都在和反射机制打交道,无论你使用的Eclipse系列的IDE(集成开发环境),还是使用的目前较为流行的IntelliJ IDEA,又或者是NetBeans,在你输入一个对象的名称,按下”.”时,总会弹出这个对象所拥有的所有方法列表供选择。这个功能就是反射机制实现的,反射机制得到了这个对象的方法和属性。
很显然,是先有的反射机制,才有的自动智能提示,所以上面的例子只能勉强算作反射机制出现和应用的一个动机。
在反射机制设计之初,睿智的设计者们或许就有了分布式的野心。编程人员希望Java能够提供在跨网络的远程平台上创建和运行对象的能力,这种能力的名字大家应该很熟悉,叫做远程方法调用RMI,这便是编程人员想要在运行时获取类的信息的又一个动机。RMI允许一个Java程序将对象分布到多台机器上,即在远程就可以调用某个对象,就像你通过浏览器去使用别人提供的网页服务一样。这就促成了现在的分布式系统的崛起。然而在JDK的1.1版本中,Java反射机制就出现了。
5,Java反射机制的类库支持及简介
Class类和java.lang.reflect类库一起构成了对Java反射机制的支持。其中最常使用到的类是Constructor,Field,Method,而这三个类都继承了一个接口java.lang.reflect.Member。下面列举介绍一下java.lang.reflect类库中的类:
- AccessibleObject:Field,Method,和Constructor对象的基类。提供了将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力。
- Array:提供了动态创建和访问Java数组的方法。
- Constructor:提供关于类的单个构造方法的信息以及对它的访问权限。
- Field: 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
- Method: 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
- Modifier: 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。该类的字段均是int类型的变量。
- Proxy: 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
- ReflectPermission:反射操作的 Permission 类。ReflectPermission 是一种指定权限,没有动作。当前定义的唯一名称是 suppressAccessChecks,它允许取消由反射对象在其使用点上执行的标准 Java 语言访问检查 - 对于 public、default(包)访问、protected、private 成员。
当要使用反射机制去探查一个类的内部时,还可以调用getFields(),getMethods()和getConstructors()等很便利的方法。对于反射机制,和RTTI的区别就在于,RTTI是在编译时打开和检查.class文件,而反射机制是在运行时打开和检查.class文件。
6,反射机制使用Demo
1.Class类是反射机制的起源,我们得到Class类对象有三种方法:
Class.forName() Object.getClass() 类字面常量xx.class
解释一下这三种方法,
- 第一种方法是Class类自带的方法,
- 第二种方法是所有的对象都能够使用的方法,因为getClass()方法是Object类的方法,所有的类都继承了Object,因此所有类的对象也都具有getClass()方法。
- 第三种方法是类字面常量。Thinking in Java中建议使用类字面常量来生成对Class对象的引用,这样做即简单又安全,因为在编译时就会受到检查,因此不需要置于try语句块中,并且它根除了对forName()方法的调用,所以也更高效。可以想象一下JDBC的语法,在加载驱动的时候,使用的就是forName()方法,因此即使单独这一句程序,也要使用try语句块。
类字面常量使得创建Class对象的引用时不会自动地初始化该对象,而是按照之前提到的加载,链接,初始化三个步骤,这三个步骤是个懒加载的过程,不使用的时候就不加载,这种机制是C/C++无法复制模拟的。
其他DEMO
- Java反射机制demo(一)—实例化Class对象,并获得其他类包名和类型
- Java反射机制demo(二)—通过Class实例化任意类的对象
- Java反射机制demo(三)—获取类中的构造函数
- Java反射机制demo(四)—获取一个类的父类和实现的接口
- Java反射机制demo(五)—获得并调用一个类中的方法
- Java反射机制demo(六)—获得并操作一个类的属性
Java反射机制Reflection的更多相关文章
- Java - 反射机制(Reflection)
Java - 反射机制(Reflection) > Reflection 是被视为 动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的 ...
- java反射机制--reflection
反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分.在java语言中这是一个很重要的特性.下面是来自sun公司官网关于反射的介绍: Reflection is ...
- Java反射机制(Reflection)
Java反射机制(Reflection) 一.反射机制是什么 Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种 ...
- Java反射机制专题
·Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方 ...
- java反射机制深入详解
java反射机制深入详解 转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...
- 反射——Java反射机制
反射概述 什么是反射? ① 反射的概念是由Smith在1982年首次提出的,主要指程序可以访问.检测和修改它本身状态或行为的一种能力. ② JAVA反射机制是在运行状态中,对应任意一个类,都能 ...
- Java反射机制详解
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...
- Java反射机制的学习
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- Java反射机制深入研究
ava 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”. 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? ...
随机推荐
- dhtmlx3.6 grid列头合并
mygrid.setHeader("序号,操作人员,发药,#cspan,审核,#cspan,数量小计,金额小计");mygrid.attachHeader(["#rspa ...
- java面试梳理
自己整理的有关java面试过的问题,有错的请矫正. 1, Spring的核心思想 控制反转和面向切面的编程 2,Spring的核心模块 反向控制与依赖注入.Bean配置以及加载 3,Scope是什么 ...
- 2015/9/29 Python基础(20):类的授权
类的授权 1.包装包装在Python编程世界中时经常会被提到的一个术语.它是一个通用的名字,意思是对一个已存在的对象进行包装,不管它是数据类型,还是一段代码,可以是对一个已存在的对象,增加新的,删除不 ...
- 【CodeForces】679 B. Bear and Tower of Cubes
[题目]B. Bear and Tower of Cubes [题意]有若干积木体积为1^3,2^3,...k^3,对于一个总体积X要求每次贪心地取<=X的最大积木拼上去(每个只能取一次)最后总 ...
- 快速入门react
安装react npm install creat-react-app -g这里直接安装react的一个脚手架,里面包含了要用到的许多东西,帮助快速入门react 创建新项目 create-react ...
- angular 最大字数限制
js可以通过onkeyup onkeydown判断当前节点字数. angular可以通过监听的方式: $scope.input = {//初始化,避免ng-model绑定取不到值 MaxBT:'', ...
- py,pyc,pyw文件的区别和使用
熟悉python编程的都知道,python三种最常见的py文件格式,.py,.pyc,.pyw,下面说一说它们各自的使用. py文件 python最常见的文件,是python项目的源码: 文件执行时l ...
- 72.xilinx vivado zynq vdma仿真及应用详解(一)
很多人用zynq平台做视频图像开发,但是对vdma了解比较少,上手起来稍微有些困难,我针对这一现象,做了一个基于vivado和modelsim的仿真和应用测试工程,并写篇文章做些介绍,希望能对大家有帮 ...
- shell编程===执行shell脚本的四种方法
使用vim创建一个shell文件,命名 hello.sh #!/bin/bash echo "hello shell !" 在linux中进行加载 chmod +x ./hello ...
- Tomcat参数调优包括日志、线程数、内存【转】
[Tomcat中日志打印对性能测试的影响] 一般都提供了这样5个日志级别: ▪ Debug ▪ Info ▪ Warn ▪ Error ▪ Fatal 由于性能测试需要并发进行压力测试,如果日志级别是 ...