Java反射机制深入研究.docx
- 文档编号:6906816
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:16
- 大小:21.55KB
Java反射机制深入研究.docx
《Java反射机制深入研究.docx》由会员分享,可在线阅读,更多相关《Java反射机制深入研究.docx(16页珍藏版)》请在冰豆网上搜索。
Java反射机制深入研究
Java反射机制深入研究
Java反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
对于任意一个对象,能否调用它的任意一个方法?
答案是肯定的。
这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。
Java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
Reflection是Java被视为动态(或准动态)语言的一个关键性质。
这个机制允许程序在运行时透过ReflectionAPIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public,static等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。
一般而言,开发者社群说到动态语言,大致认同的一个定义是:
“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。
从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:
Reflection。
这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
这种“看透class”的能力(theabilityoftheprogramtoexamineitself)被称为introspection(内省、内观、反省)。
Reflection和introspection是常被并提的两个术语。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:
代表一个类。
Field类:
代表类的成员变量(成员变量也称为类的属性)。
Method类:
代表类的方法。
Constructor类:
代表类的构造方法。
Array类:
提供了动态创建数组,以及访问数组的元素的静态方法。
下面给出几个例子看看ReflectionAPI的实际运用:
一、通过Class类获取成员变量、成员方法、接口、超类、构造方法等
在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。
Class类是ReflectionAPI中的核心类,它有以下方法
getName():
获得类的完整名字。
getFields():
获得类的public类型的属性。
getDeclaredFields():
获得类的所有属性。
getMethods():
获得类的public类型的方法。
getDeclaredMethods():
获得类的所有方法。
getMethod(Stringname,Class[]parameterTypes):
获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
getConstructors():
获得类的public类型的构造方法。
getConstructor(Class[]parameterTypes):
获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。
newInstance():
通过类的不带参数的构造方法创建这个类的一个对象。
下面给出一个综合运用的例子:
publicclassRefConstructor{
publicstaticvoidmain(Stringargs[])throwsException{
RefConstructorref=newRefConstructor();
ref.getConstructor();
}
publicvoidgetConstructor()throwsException{
Classc=null;
c=Class.forName("java.lang.Long");
Classcs[]={java.lang.String.class};
System.out.println("\n-------------------------------\n");
Constructorcst1=c.getConstructor(cs);
System.out.println("1、通过参数获取指定Class对象的构造方法:
");
System.out.println(cst1.toString());
Constructorcst2=c.getDeclaredConstructor(cs);
System.out.println("2、通过参数获取指定Class对象所表示的类或接口的构造方法:
");
System.out.println(cst2.toString());
Constructorcst3=c.getEnclosingConstructor();
System.out.println("3、获取本地或匿名类Constructor对象,它表示基础类的立即封闭构造方法。
");
if(cst3!
=null)System.out.println(cst3.toString());
elseSystem.out.println("--没有获取到任何构造方法!
");
Constructor[]csts=c.getConstructors();
System.out.println("4、获取指定Class对象的所有构造方法:
");
for(inti=0;i System.out.println(csts[i].toString()); } System.out.println("\n-------------------------------\n"); Typetypes1[]=c.getGenericInterfaces(); System.out.println("1、返回直接实现的接口: "); for(inti=0;i System.out.println(types1[i].toString()); } Typetype1=c.getGenericSuperclass(); System.out.println("2、返回直接超类: "); System.out.println(type1.toString()); Class[]cis=c.getClasses(); System.out.println("3、返回超类和所有实现的接口: "); for(inti=0;i System.out.println(cis[i].toString()); } Classcs1[]=c.getInterfaces(); System.out.println("4、实现的接口"); for(inti=0;i System.out.println(cs1[i].toString()); } System.out.println("\n-------------------------------\n"); Fieldfs1[]=c.getFields(); System.out.println("1、类或接口的所有可访问公共字段: "); for(inti=0;i System.out.println(fs1[i].toString()); } Fieldf1=c.getField("MIN_VALUE"); System.out.println("2、类或接口的指定已声明指定公共成员字段: "); System.out.println(f1.toString()); Fieldfs2[]=c.getDeclaredFields(); System.out.println("3、类或接口所声明的所有字段: "); for(inti=0;i System.out.println(fs2[i].toString()); } Fieldf2=c.getDeclaredField("serialVersionUID"); System.out.println("4、类或接口的指定已声明指定字段: "); System.out.println(f2.toString()); System.out.println("\n-------------------------------\n"); Methodm1[]=c.getMethods(); System.out.println("1、返回类所有的公共成员方法: "); for(inti=0;i System.out.println(m1[i].toString()); } Methodm2=c.getMethod("longValue",newClass[]{}); System.out.println("2、返回指定公共成员方法: "); System.out.println(m2.toString()); } } 输出结果: 输出结果很长,这里不再给出。 二、运行时复制对象 例程ReflectTester类进一步演示了ReflectionAPI的基本使用方法。 ReflectTester类有一个copy(Objectobject)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回 这个例子只能复制简单的JavaBean,假定JavaBean的每个属性都有public类型的getXXX()和setXXX()方法。 publicclassReflectTester{ publicObjectcopy(Objectobject)throwsException{ //获得对象的类型 Class >classType=object.getClass(); System.out.println("Class: "+classType.getName()); //通过默认构造方法创建一个新的对象 ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{}); //获得对象的所有属性 Fieldfields[]=classType.getDeclaredFields(); for(inti=0;i Fieldfield=fields[i]; StringfieldName=field.getName(); StringfirstLetter=fieldName.substring(0,1).toUpperCase(); //获得和属性对应的getXXX()方法的名字 StringgetMethodName="get"+firstLetter+fieldName.substring (1); //获得和属性对应的setXXX()方法的名字 StringsetMethodName="set"+firstLetter+fieldName.substring (1); //获得和属性对应的getXXX()方法 MethodgetMethod=classType.getMethod(getMethodName,newClass[]{}); //获得和属性对应的setXXX()方法 MethodsetMethod=classType.getMethod(setMethodName,newClass[]{field.getType()}); //调用原对象的getXXX()方法 Objectvalue=getMethod.invoke(object,newObject[]{}); System.out.println(fieldName+": "+value); //调用拷贝对象的setXXX()方法 setMethod.invoke(objectCopy,newObject[]{value}); } returnobjectCopy; } publicstaticvoidmain(String[]args)throwsException{ Customercustomer=newCustomer("Tom",21); customer.setId(newLong (1)); CustomercustomerCopy=(Customer)newReflectTester().copy(customer); System.out.println("Copyinformation: "+customerCopy.getId()+""+customerCopy.getName()+"" +customerCopy.getAge()); } } classCustomer{ privateLongid; privateStringname; privateintage; publicCustomer(){ } publicCustomer(Stringname,intage){ this.name=name; this.age=age; } publicLonggetId(){ returnid; } publicvoidsetId(Longid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicintgetAge(){ returnage; } publicvoidsetAge(intage){ this.age=age; } } 输出结果: Class: com.langsin.reflection.Customer id: 1 name: Tom age: 21 Copyinformation: 1Tom21 Processfinishedwithexitcode0 解说: ReflectTester类的copy(Objectobject)方法依次执行以下步骤 (1)获得对象的类型: ClassclassType=object.getClass(); System.out.println("Class: "+classType.getName()); (2)通过默认构造方法创建一个新对象: ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{}); 以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。 3)获得对象的所有属性: Fieldfields[]=classType.getDeclaredFields(); Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性 (4)获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性拷贝到新的对象中 三、用反射机制调用对象的方法 publicclassInvokeTester{ publicintadd(intparam1,intparam2){ returnparam1+param2; } publicStringecho(Stringmsg){ return"echo: "+msg; } publicstaticvoidmain(String[]args)throwsException{ Class >classType=InvokeTester.class; ObjectinvokeTester=classType.newInstance(); //ObjectinvokeTester=classType.getConstructor(new //Class[]{}).newInstance(newObject[]{}); //获取InvokeTester类的add()方法 MethodaddMethod=classType.getMethod("add",newClass[]{int.class,int.class}); //调用invokeTester对象上的add()方法 Objectresult=addMethod.invoke(invokeTester,newObject[]{newInteger(100),newInteger(200)}); System.out.println((Integer)result); //获取InvokeTester类的echo()方法 MethodechoMethod=classType.getMethod("echo",newClass[]{String.class}); //调用invokeTester对象的echo()方法 result=echoMethod.invoke(invokeTester,newObject[]{"Hello"}); System.out.println((String)result); } } 在例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法 add()方法的两个参数为int类型,获得表示add()方法的Method对象的代码如下: MethodaddMethod=classType.getMethod("add",newClass[]{int.class,int.class}); Method类的invoke(Objectobj,Objectargs[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。 invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。 在本例中,尽管InvokeTe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 反射 机制 深入 研究
![提示](https://static.bdocx.com/images/bang_tan.gif)