您的位置:首页 > 编程语言 > Java开发

Java 反射机制(一)

2016-05-14 19:00 676 查看
  阅读《Core Java Volume I --- Fundamentals》反射部分,总觉得许多概念艰涩难懂、模棱两可。我想造成这个结果的主要原因可能是Cay S. Horstmann和Gary Cornell这两位大牛认为阅读本书的读者可能并不具备深入了解Java虚拟机技术的知识基础或根本没有精力去啃《深入Java虚拟机》这本经典巨著,为了能够介绍反射概念又不至于让读者大量阅读文献资料,因此有些东西(可能这些内容就是一门系统的课程)只能这么轻飘飘地一笔带过。如果是你是一个有心人,对书中的字眼加以琢磨,仍然会得到很大的收获和提升。

  本文主要对《Core Java Volume I --- Fundamentals》中以下概念加以解释:

  1. 反射反射库反射机制

  2. 动态加载类静态加载类

  3. Class类

一、Java 反射概念

  Java反射概念涉及到反射、反射库、反射机制这几个核心词。

  1)反射(Reflective)

  《Core Java》中文第9版中这么定义:能够分析类能力的程序称为反射(reflective)。带着对这句定义的反对想法,查阅了《Core Java》英文第9版,情况如下图所示。显然直译结果是没有任何问题的,那么也就是说:反射指对相应类具有检查、访问、修改能力的程序

  

  

  2)反射库(Reflection Library)

  The reflection library gives you a very rich and elaborate toolset to write programs that manipulate Java code dynamically.

  反射库指的是 java.lang.reflect 包中相应的类及接口。

  3)反射机制(Reflection Mechanism)

  绝大多数文献资料,貌似都对反射反射机制这两个概念几乎不区别,就像指针和指针变量这般。但是显然这两者在单词上,无论是中文还是英文都是有区别的。个人认为反射机制强调的是反射实现过程或者其内容;而反射则强调程序本身,是一个比较整体的概念。

二、JVM 类加载机制

  此处不是想详细讲明JVM如何通过各种类装载器(例如ClassLoader)对字节码如何加载以及加载顺序问题。而是想谈谈两个概念:静态加载类、动态加载类。如果读者经常使用IDE工具开发Java程序,对JVM静态加载、动态加载的区别或许会感受不深;而如果使用普通的记事本进行编译、解释则会帮助你对Java体系有更好的理解。

  1)静态加载类

  指的是在通过javac编译Java程序时需要将可能需要的类都加载一遍,否则编译器将不能通过编译。此种情况是不使用Java反射机制产生的情况。

  2)动态加载类

  指的是在用javac编译Java程序时不必要将所有类都加载,即不全部加载可能需要类也能通过编译。不过,在运行时环境中,程序会根据实际需要的内容装载相应的字节码文件。因此,Java反射机制使用的动态加载类方式明显比静态加载类要优异,具有交互性优异等特点。

三、Java Class类

  Java的Class类内容定义在java.lang.Class中。由于网上资料解释不清以及对Class类的理解具有哲学高度等原因,读者往往会对Class类具有一定的理解困难。

  网上资料通常会说,Java语言中,万物皆对象(除static、primitive types外),所有的类都是java.lang.Class类的对象诸如此类等等的概念。那么该如何理解这些概念呢?

  本文将从另一个视角带读者认识Class类。根据《Core Java》英文第9版中的一段话来进入这篇文章所要阐述的最重要观点。



  在你的程序运行期间,Java运行时系统总会为对象维持一个运行时类型标志。这个运行时类型标志跟踪每一个对象所属相应类的信息。Java虚拟机使用这些运行时类型信息来选择执行合适的方法。

  然而,你也能够通过专门的Java类来访问运行时类型信息。持有这些运行时类型标志信息的类就是这个有点令人不知所措的Class。Object类中的getClass()方法返回Class类型的实例。

  看完我翻译完的这段话后,不知你是否已经略微了解Class类了呢?其实我个人是很讨厌有人把Class Type翻译成类类型,觉得这就像在扯淡。Class类型(或Class Type)本身能够清楚表明意思,但是类类型其实是一个很令人费解的词。

  通过一幅"截肢"过的JVM运行时系统图或许能够比较形象地说明这个问题。当然图画的不太完整,略微用文字描述一下。



  如果我们现在有一个类Human,创建其对象Human hm = new Human();那么这句话大致是依次干了如下几件事:

  a)JVM通过类装载器,先装入系统预定义的类字节码,然后装入自定义的类Human字节码到方法区。

  b)然后开始创建对象,将对象静态成员变量、方法保存在Class类中,将方法做成一张查询的虚表。

  c)在非栈(堆)中用一个指针指向方法区的虚表,并将对象其余属性也装入非栈(堆)中。

  d)在虚拟机堆中对象生成一个hash值,即对象的句柄。这个句柄值被浅拷贝到虚拟机栈中储存。

  当然,必须说明:上述的只是一种帮助理解的简化模型,真实的情况并非如此,而且复杂地多

  回到问题本身,Class类本身就是一种最泛化的概念。看它的名字"Class"就能够体会到,人类已经无法用别的名字来表述所有类的共性了,因而就用Class来表示所有class的共性。Class是所有具体class的抽象,反过来,也就是说具体class类都是Class的具体实例,即有了对象的概念。

  不得不提的是,正式因为有了Java反射机制,才有了Java泛型编程的广泛应用。具体的内容将会在后续的文章中细说。

  

  声明:文章系作者原创,转载需通过作者同意。由于作者水平有限,部分内容可能存在错误,还望谅解。

  

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: