JAVA反射机制定义14页精选文档文档格式.docx
- 文档编号:22525297
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:20
- 大小:26.73KB
JAVA反射机制定义14页精选文档文档格式.docx
《JAVA反射机制定义14页精选文档文档格式.docx》由会员分享,可在线阅读,更多相关《JAVA反射机制定义14页精选文档文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
我们朗朗上口动态绑定(dynamicbinding)、动态链接(dynamiclinking)、动态加载(dynamicloading)等。
然而“动态”一词其实没有绝对而普遍适用的严格定义,有时候甚至像对象导向当初被导入编程领域一样,一人一把号,各吹各的调。
一般而言,开发者社群说到动态语言,大致认同的一个定义是:
“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。
从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:
Reflection。
这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods1。
这种“看透class”的能力(theabilityoftheprogramtoexamineitself)被称为introspection(内省、内观、反省)。
Reflection和introspection是常被并提的两个术语。
Java如何能够做出上述的动态特性呢?
这是一个深远话题,本文对此只简单介绍一些概念。
整个篇幅最主要还是介绍ReflectionAPIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。
本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。
编辑本段“Class”cla
众所周知Java有个Objectclass,是所有Javaclasses的继承根源,其内声明了数个应该在所有Javaclass中被改写的methods:
hashCode()、equals()、clone()、toString()、getClass()等。
其中getClass()返回一个Classobject。
Classclass十分特殊。
它和一般classes一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitiveJavatypes(boolean,byte,char,short,int,long,float,double)以及关键词void。
当一个class被加载,或当加载器(classloader)的defineClass()被JVM调用,JVM便自动产生一个Classobject。
如果您想借由“修改Java标准库源码”来观察Classobject的实际生成时机(例如在Class的constructor内添加一个println()),不能够!
因为Class并没有publicconstructor(见图1)。
本文最后我会拨一小块篇幅顺带谈谈Java标准库源码的改动办法。
Class是Reflection故事起源。
针对任何您想探勘的class,唯有先为它产生一个Classobject,接下来才能经由后者唤起为数十多个的ReflectionAPIs。
这些APIs将在稍后的探险活动中一一亮相。
#001publicfinal
#002classClass<
T>
implementsSerializable,
#003java.lang.reflect.GenericDeclaration,
#004java.lang.reflect.Type,
#005java.lang.reflect.AnnotatedElement{
#006privateClass(){}
#007publicStringtoString(){
#008return(isInterface()?
"
interface"
:
#009(isPrimitive()?
"
class"
))
#010+getName();
#011}
图1:
Classclass片段。
注意它的privateemptyctor,意指不允许任何人经由编程方式产生Classobject。
是的,其object只能由JVM产生。
编辑本段“Class”object的取得途径
Java允许我们从多种管道为一个class生成对应的Classobject。
图2是一份整理。
Classobject诞生管道
示例
运用getClass()
注:
每个class都有此函数
Stringstr="
abc"
;
Classc1=str.getClass();
运用
Class.getSuperclass()2
Buttonb=newButton();
Classc1=b.getClass();
Classc2=c1.getSuperclass();
运用staticmethod
Class.forName()
(最常被使用)
Classc1=Class.forName("
java.lang.String"
);
Classc2=Class.forName("
java.awt.Button"
Classc3=Class.forName("
java.utiledList$Entry"
Classc4=Class.forName("
I"
Classc5=Class.forName("
.class;
primitivewrapperclasses
的TYPE语法
Classc1=Boolean.TYPE;
Classc2=Byte.TYPE;
Classc3=Character.TYPE;
Classc4=Short.TYPE;
Classc5=Integer.TYPE;
Classc6=Long.TYPE;
Classc7=Float.TYPE;
Classc8=Double.TYPE;
Classc9=Void.TYPE;
图2:
Java允许多种管道生成Classobject。
Javaclasses组成分析
首先容我以图3的java.utiledList为例,将Javaclass的定义大卸八块,每一块分别对应图4所示的ReflectionAPI。
图5则是“获得class各区块信息”的程序示例及执行结果,它们都取自本文示例程序的对应片段。
packagejava.util;
//
(1)
importjava.lang.*;
//
(2)
publicclassLinkedList<
E>
//(3)(4)(5)
extendsAbstractSequentialList<
//(6)
implementsList<
Queue<
Cloneable,.Serializable//(7)
privatestaticclassEntry<
{…}//(8)
publicLinkedList(){…}//(9)
publicLinkedList(Collection<
?
extendsE>
c){…}
publicEgetFirst(){…}//(10)
publicEgetLast(){…}
privatetransientEntry<
header=…;
//(11)
privatetransientintsize=0;
图3:
将一个Javaclass大卸八块,每块相应于一个或一组ReflectionAPIs(图4)。
编辑本段各成份所对应的API
图3的各个Javaclass成份,分别对应于图4的ReflectionAPI,其中出现的Package、Method、Constructor、Field等等classes,都定义于java.lang.reflect。
Javaclass内部模块(参见图3)
Javaclass内部模块说明
相应之ReflectionAPI,多半为Classmethods。
返回值类型(returntype)
(1)package
class隶属哪个package
getPackage()
Package
(2)import
class导入哪些classes
无直接对应之API。
解决办法见图5-2。
(3)modifier
class(或methods,fields)的属性
intgetModifiers()
Modifier.toString(int)
Modifier.isInterface(int)
int
String
bool
(4)classnameorinterfacename
class/interface
名称getName()
(5)typeparameters
参数化类型的名称
getTypeParameters()
TypeVariable<
Class>
[]
(6)baseclass
baseclass(只可能一个)
getSuperClass()
Class
(7)implementedinterfaces
实现有哪些interfaces
getInterfaces()
Class[]
(8)innerclasses
内部classes
getDeclaredClasses()
(8'
)outerclass
如果我们观察的class本身是innerclasses,那么相对它就会有个outerclass。
getDeclaringClass()
(9)constructors
构造函数getDeclaredConstructors()
不论public或private或其它accesslevel,皆可获得。
另有功能近似之取得函数。
Constructor[]
(10)methods
操作函数getDeclaredMethods()
Method[]
(11)fields
字段(成员变量)
getDeclaredFields()不论public或private或其它accesslevel,皆可获得。
Field[]
图4:
Javaclass大卸八块后(如图3),每一块所对应的ReflectionAPI。
本表并非
ReflectionAPIs的全部。
JavaReflectionAPI运用示例
图5示范图4提过的每一个ReflectionAPI,及其执行结果。
程序中出现的tName()是个辅助函数,可将其第一自变量所代表的“Javaclass完整路径字符串”剥除路径部分,留下class名称,储存到第二自变量所代表的一个hashtable去并返回(如果第二自变量为null,就不储存而只是返回)。
#001Classc=null;
#002c=Class.forName(args[0]);
#003
#004Packagep;
#005p=c.getPackage();
#006
#007if(p!
=null)
#008System.out.println("
package"
+p.getName()+"
执行结果(例):
图5-1:
找出class隶属的package。
其中的c将继续沿用于以下各程序片段。
#001ff=c.getDeclaredFields();
#002for(inti=0;
i<
ff.length;
i++)
#003x=tName(ff.getType().getName(),classRef);
#004
#005cn=c.getDeclaredConstructors();
#006for(inti=0;
cn.length;
i++){
#007Classcx[]=cn.getParameterTypes();
#008for(intj=0;
j<
cx.length;
j++)
#009x=tName(cx[j].getName(),classRef);
#010}
#011
#012mm=c.getDeclaredMethods();
#013for(inti=0;
mm.length;
#014x=tName(mm.getReturnType().getName(),classRef);
#015Classcx[]=mm.getParameterTypes();
#016for(intj=0;
#017x=tName(cx[j].getName(),classRef);
#018}
#019classRef.remove(c.getName());
//不必记录自己(不需import自己)
importjava.util.ListIterator;
importjava.lang.Object;
importjava.utiledList$Entry;
importjava.util.Collection;
importObjectOutputStream;
import.ObjectInputStream;
图5-2:
找出导入的classes,动作细节详见内文说明。
#001intmod=c.getModifiers();
#002System.out.print(Modifier.toString(mod));
//整个modifier
#004if(Modifier.isInterface(mod))
#005System.out.print("
//关键词"
interface"
已含于modifier
#006else
#007System.out.print("
class"
class"
#008System.out.print(tName(c.getName(),null));
//class名称
publicclassLinkedList
图5-3:
找出class或interface的名称,及其属性(modifiers)。
#001TypeVariable<
[]tv;
#002tv=c.getTypeParameters();
//warning:
uncheckedconversion
#003for(inti=0;
tv.length;
#004x=tName(tv.getName(),null);
//例如E,K,V...
#005if(i==0)//第一个
#006System.out.print("
<
+x);
#007else//非第一个
#008System.out.print("
"
#009if(i==tv.length-1)//最后一个
#010System.out.println("
>
publicabstractinterfaceMap<
K,V>
或publicclassLinkedList<
图5-4:
找出parameterizedtypes的名称
#001ClasssupClass;
#002supClass=c.getSuperclass();
#003if(supClass!
=null)//如果有superclass
#004System.out.print("
extends"
+
#005tName(supClass.getName(),classRef));
extendsAbstractSequentialList,
图5-5:
找出baseclass。
执行结果多出一个不该有的逗号于尾端。
此非本处重点,为简化计,不多做处理。
#001Classcc[];
#002Classctmp;
#003//找出所有被实现的interfaces
#004cc=c.getInterfaces();
#005if(cc.length!
=0)
\r\n"
+"
implements"
//关键词
#007for(Classcite:
cc)//JDK1.5新式循环写法
#008System.out.print(tName(cite.getName(),null)+"
"
implementsList,Queue,Cloneable,Serializable,
图5-6:
找出implementedinterfaces。
#001cc=c.getDeclaredClasses();
//找出innerclasses
#002for(Classcite:
cc)
#003System.out.println(tName(cite.getName(),null));
#005ctmp=c.getDeclaringClass();
//找出outerclasses
#006if(ctmp!
#007System.out.println(ctmp.getName());
LinkedList$Entry
LinkedList$ListItr
图5-7:
找出innerclasses和outerclass
#001Constructorcn[];
#002cn=c.getDeclaredConstructors();
#004intmd=cn.getModifiers();
+Modifier.toString(md)+"
#006cn.getName());
#007Classcx[]=cn.getParameterTyp
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JAVA 反射 机制 定义 14 精选 文档