候捷谈Java反射机制

系统 1546 0

有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。我们朗朗上口动态绑定( dynamic binding )、动态链接( dynamic linking )、动态加载( dynamic loading )等。然而 动态 一词其实没有绝对而普遍适用的严格定义,有时候甚至像对象导向当初被导入编程领域一样,一人一把号,各吹各的调。

 

一般而言,开发者社群说到动态语言,大致认同的一个定义是: 程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言 。从这个观点看, Perl Python Ruby 是动态语言, C++ Java C# 不是动态语言。

 

尽管在这样的定义与分类下 Java 不是动态语言,它却有着一个非常突出的动态相关机制: Reflection 。这个字的意思是 反射、映象、倒影 ,用在 Java 身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的 classes 。换句话说, Java 程序可以加载一个运行时才得知名称的 class ,获悉其完整构造(但不包括 methods 定义),并生成其对象实体、或对其 fields 设值、或唤起其 methods 1 。这种 看透 class 的能力( the ability of the program to examine itself )被称为 introspection 内省、内观、反省 )。 Reflection introspection 是常被并提的两个术语。

 

Java 如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个篇幅最主要还是介绍 Reflection APIs ,也就是让读者知道如何探索 class 的结构、如何对某个 运行时才获知名称的 class 生成一份实体、为其 fields 设值、调用其 methods 。本文将谈到 java.lang.Class ,以及 java.lang.reflect 中的 Method Field Constructor 等等 classes

 

Class class

众所周知 Java 有个 Object class ,是所有 Java classes 的继承根源,其内声明了数个应该在所有 Java class 中被改写的 methods hashCode() equals() clone() toString() getClass() 等。其中 getClass() 返回一个 Class object

 

Class class 十分特殊。它和一般 classes 一样继承自 Object ,其实体用以表达 Java 程序运行时的 classes interfaces ,也用来表达 enum array primitive Java types boolean, byte, char, short, int, long, float, double )以及关键词 void 。当一个 class 被加载,或当加载器( class loader )的 defineClass() JVM 调用, JVM 便自动产生一个 Class object 。如果您想借由 修改 Java 标准库源码 来观察 Class object 的实际生成时机(例如在 Class constructor 内添加一个 println() ),不能够!因为 Class 并没有 public constructor (见 1 )。本文最后我会拨一小块篇幅顺带谈谈 Java 标准库源码的改动办法。

 

Class Reflection 故事起源。针对任何您想探勘的 class ,唯有先为它产生一个 Class object ,接下来才能经由后者唤起为数十多个的 Reflection APIs 。这些 APIs 将在稍后的探险活动中一一亮相。

 

#001 public final

#002 class Class <T> implements java.io.Serializable,

#003 java.lang.reflect.GenericDeclaration,

#004 java.lang.reflect.Type,

#005 java.lang.reflect.AnnotatedElement {

#006    private Class() {}

#007    public String toString () {

#008        return ( isInterface() ? "interface " :

#009        (isPrimitive() ? "" : "class "))

#010    + getName();

#011 }

...

1 Class class 片段。注意它的 private empty ctor ,意指不允许任何人经由编程方式产生 Class object 。是的,其 object 只能由 JVM 产生。

 

Class object 的取得途径

Java 允许我们从多种管道为一个 class 生成对应的 Class object 2 是一份整理。

Class object 诞生管道

示例

运用 getClass()

注:每个 class 都有此函数

String str = "abc";

Class c1 = str.getClass();

运用

Class.getSuperclass() 2

Button b = new Button();

Class c1 = b.getClass();

Class c2 = c1.getSuperclass();

运用 static method

Class.forName()

(最常被使用)

Class c1 = Class.forName ("java.lang.String");

Class c2 = Class.forName ("java.awt.Button");

Class c3 = Class.forName ("java.util.LinkedList$Entry");

Class c4 = Class.forName ("I");

Class c5 = Class.forName ("[I");

运用

.class 语法

Class c1 = String.class;

Class c2 = java.awt.Button.class;

Class c3 = Main.InnerClass.class;

Class c4 = int.class;

Class c5 = int[].class;

运用

primitive wrapper classes

TYPE 语法

 

Class c1 = Boolean.TYPE;

Class c2 = Byte.TYPE;

Class c3 = Character.TYPE;

Class c4 = Short.TYPE;

Class c5 = Integer.TYPE;

Class c6 = Long.TYPE;

Class c7 = Float.TYPE;

Class c8 = Double.TYPE;

Class c9 = Void.TYPE;

2 Java 允许多种管道生成 Class object

 

Java classes 组成分析

首先容我以 3 java.util.LinkedList 为例,将 Java class 的定义大卸八块,每一块分别对应 4 所示的 Reflection API 5 则是“获得 class 各区块信息”的程序示例及执行结果,它们都取自本文示例程序的对应片段。

 

package java.util;                      //(1)

import java.lang.*;                     //(2)

public class LinkedList < E >              //(3)(4)(5)

extends AbstractSequentialList <E>       //(6)

implements List <E>, Queue <E>,

Cloneable, java.io.Serializable         //(7)

{

private static class Entry <E> { }//(8)

public LinkedList () { }           //(9)

public LinkedList (Collection<? extends E> c) { }

public E getFirst () { }           //(10)

public E getLast () { }

private transient Entry<E> header = ;   //(11)

private transient int size = 0;

}

3 :将一个 Java class 大卸八块,每块相应于一个或一组 Reflection APIs (图 4 )。

 

Java classes 各成份所对应的 Reflection APIs

3 的各个 Java class 成份,分别对应于 4 Reflection API ,其中出现的 Package Method Constructor Field 等等 classes ,都定义于 java.lang.reflect

Java class 内部模块(参见 3

Java class 内部模块说明

相应之 Reflection API ,多半为 Class methods

返回值类型 (return type)

(1) package

class 隶属哪个 package

getPackage()

Package

(2) import

class 导入哪些 classes

border-style: none solid solid none; border-color: rgb(236, 233, 216) windowtext windowtext rgb(236, 233, 21
分享到:
评论
wyjaw
  • 浏览: 9592 次
  • 性别: Icon_minigender_2
  • 来自: 北京
最近访客 更多访客>>
文章分类
最新评论

候捷谈Java反射机制


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论