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. Codechef Dynamic Trees and Queries

    Home » Practice(Hard) » Dynamic Trees and Queries Problem Code: ANUDTQSubmit https://www.codechef.co ...

  2. 2-sat Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) D

    http://codeforces.com/contest/782/problem/D 题意: 每个队有两种队名,问有没有满足以下两个条件的命名方法: ①任意两个队的名字不相同. ②若某个队 A 选用 ...

  3. 原生js写的一个简单slider

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 您是哪个等级的CSS开发人员?

    我们在不断的学习,追求进步与提高,到底学到什么程度了,到底是 不是真的了解CSS,是哪个层次了呢.我们来对照一下. 第0级:CSS?那不是一个多人射击游戏吗?  CSS? Isn't that a m ...

  5. Palindromic Squares 回文平方数

    1.2.4 Palindromic Squares 回文平方数 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 139  Solved: 66[Submit ...

  6. 利用media query写响应式布局

    最近才接触到响应式布局的概念,之前用到的bootstrap就是一种响应式布局的框架.学习的时候参考了http://blog.csdn.net/shoyer/article/details/829301 ...

  7. Intersection(HDU5120 + 圆交面积)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5120 题目: 题意: 求两个圆环相交的面积. 思路: 两个大圆面积交-2×大圆与小圆面积交+两小圆面 ...

  8. PHPMailer发送邮件(一)

    Github 地址:(已更新,适用于旧版) PHPMailer : https://github.com/PHPMailer/PHPMailer 一.基本要求 Web访问正常(apache可以正常访问 ...

  9. docker 加速

    Docker配置阿里云加速地址 打开阿里云网站https://cr.console.aliyun.com,登陆自己的阿里云账号. 然后只需要在服务器配置docker配置文件,只需要修改"Ex ...

  10. 图解IIS8上解决ASP.Net第一次访问慢的处理