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反射机制Reflection的更多相关文章

  1. Java - 反射机制(Reflection)

    Java - 反射机制(Reflection)     > Reflection 是被视为 动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的       ...

  2. java反射机制--reflection

    反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分.在java语言中这是一个很重要的特性.下面是来自sun公司官网关于反射的介绍:    Reflection is ...

  3. Java反射机制(Reflection)

    Java反射机制(Reflection) 一.反射机制是什么 Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种 ...

  4. Java反射机制专题

    ·Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方 ...

  5. java反射机制深入详解

    java反射机制深入详解  转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...

  6. 反射——Java反射机制

    反射概述 什么是反射? ①   反射的概念是由Smith在1982年首次提出的,主要指程序可以访问.检测和修改它本身状态或行为的一种能力. ②   JAVA反射机制是在运行状态中,对应任意一个类,都能 ...

  7. Java反射机制详解

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...

  8. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  9. Java反射机制深入研究

    ava 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”.   在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? ...

随机推荐

  1. ④ 设计模式的艺术-10.装饰(Decorator)模式

    职责 装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对 ...

  2. 针对移动设备的CSS3布局

    针对移动设备的CSS3布局 一些专业人士预测五年内移动设备将击败普通电脑成为网页浏览领域的霸主,不管这个预言是否应验,让网页在移动设备上较好的显示已经成为网页设计师和开发者的重要任务,本教程学习用CS ...

  3. Docker 配置国内镜像拉取中心,Configure docker to use faster registries in China.

    Networking in China is really bad when it comes to using some cloud based tools like docker, it's us ...

  4. http://www.cnblogs.com/kkdn/

    /*** PHP保留两位小数的几种方法* @link http://www.phpddt.com*/$num = 10.4567; //第一种:利用round()对浮点数进行四舍五入echo roun ...

  5. 【洛谷 P2900】 [USACO08MAR]土地征用Land Acquisition(斜率优化,单调栈)

    题目链接 双倍经验 设\(H\)表示长,\(W\)表示宽. 若\(H_i<H_j\)且\(W_i<W_j\),显然\(i\)对答案没有贡献. 于是把所有点按\(H\)排序,然后依次加入一个 ...

  6. python初步学习-异常

    异常 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在python无法正常处理程序时就会发生一个异常. 异常是python对象,表示一个错误. 当python脚本 ...

  7. python之yagmail库笔记

    1. yagmail是啥 yagmail是给正常人用的,封装的比较彻底的一个python邮件库,发送接收邮件只需要几行代码,炒鸡简单. 2. 安装 使用pip安装,炒鸡简单: pip install ...

  8. MacOS Safari 中 button 不能使用 text-gradient

    @mixin text-gradient ($deg: 90deg, $from: $gradientFrom, $to: $gradientEnd) { background-image: line ...

  9. JS几个常用的工具函数

    一个项目中JS也不可避免会出现重用,所以可以像Java一样抽成工具类,下面总结了几个常用的函数: 1.日期处理函数 将日期返回按指定格式处理过的字符串: function Format(now,mas ...

  10. Power Profiles for Android

    http://source.android.com/devices/tech/power.html Battery usage information is derived from battery ...