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. CSS盒子知识

    此随笔写于学习完CSS盒子之后,所遇到的问题和感悟记录. 1.IE盒子: IE盒子的特性:对于IE浏览器来说width不是内容宽度.而是内容+外边距+边框的内容总和. 也就是说当盒子增加10px;那么 ...

  2. HDU 2582 规律 素因子

    定义$Gcd(n)=gcd(\binom{n}{1},\binom{n}{2}...\binom{n}{n-1})$,$f(n)=\sum_{i=3}^{n}{Gcd(i)}$,其中$(3<=n ...

  3. HDU 1299 基础数论 分解

    给一个数n问有多少种x,y的组合使$\frac{1}{x}+\frac{1}{y}=\frac{1}{n},x<=y$满足,设y = k + n,代入得到$x = \frac{n^2}{k} + ...

  4. SQL语句(二十二)—— 权限授予和回收(作业练习)

    CREATE TABLE course ( Cno ) NOT NULL, Cname ) DEFAULT NULL, Cpno ) DEFAULT NULL, Ccredit smallint DE ...

  5. [译] man 7 pthreads

    NAME      pthreads - POSIX threads   DESCRIPTION      POSIX.1 指定了一组叫做POSIX线程或Pthreads的编程接口(函数,头文件).单 ...

  6. 2016-2017-2 20155117实验二《Java面向对象程序设计》实验报告

    实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.参考Intellj IDEA 简易教程 提交 ...

  7. tp修改的写法

  8. 利用PCA可视化异常点

    异常点往往是由于某一个特征或者多个特征数值异常.但是对于多维度特征无法直接进行可视化观测异常点,利用PCA技术进行维度缩减,可以在二维或者三维空间上进行可视化展示. 原数据如下: from sklea ...

  9. 贪心算法_01背包问题_Java实现

    原文地址:http://blog.csdn.net/ljmingcom304/article/details/50310789 本文出自:[梁敬明的博客] 1.贪心算法 什么是贪心算法?是指在对问题进 ...

  10. (1)剑指Offer之斐波那契数列问题和跳台阶问题

    一 斐波那契数列 题目描述: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项. n<=39 问题分析: 可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有 ...