第十五章Java反射机制与正则表达式.docx

上传人:b****1 文档编号:2920991 上传时间:2023-05-05 格式:DOCX 页数:37 大小:134.52KB
下载 相关 举报
第十五章Java反射机制与正则表达式.docx_第1页
第1页 / 共37页
第十五章Java反射机制与正则表达式.docx_第2页
第2页 / 共37页
第十五章Java反射机制与正则表达式.docx_第3页
第3页 / 共37页
第十五章Java反射机制与正则表达式.docx_第4页
第4页 / 共37页
第十五章Java反射机制与正则表达式.docx_第5页
第5页 / 共37页
第十五章Java反射机制与正则表达式.docx_第6页
第6页 / 共37页
第十五章Java反射机制与正则表达式.docx_第7页
第7页 / 共37页
第十五章Java反射机制与正则表达式.docx_第8页
第8页 / 共37页
第十五章Java反射机制与正则表达式.docx_第9页
第9页 / 共37页
第十五章Java反射机制与正则表达式.docx_第10页
第10页 / 共37页
第十五章Java反射机制与正则表达式.docx_第11页
第11页 / 共37页
第十五章Java反射机制与正则表达式.docx_第12页
第12页 / 共37页
第十五章Java反射机制与正则表达式.docx_第13页
第13页 / 共37页
第十五章Java反射机制与正则表达式.docx_第14页
第14页 / 共37页
第十五章Java反射机制与正则表达式.docx_第15页
第15页 / 共37页
第十五章Java反射机制与正则表达式.docx_第16页
第16页 / 共37页
第十五章Java反射机制与正则表达式.docx_第17页
第17页 / 共37页
第十五章Java反射机制与正则表达式.docx_第18页
第18页 / 共37页
第十五章Java反射机制与正则表达式.docx_第19页
第19页 / 共37页
第十五章Java反射机制与正则表达式.docx_第20页
第20页 / 共37页
亲,该文档总共37页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

第十五章Java反射机制与正则表达式.docx

《第十五章Java反射机制与正则表达式.docx》由会员分享,可在线阅读,更多相关《第十五章Java反射机制与正则表达式.docx(37页珍藏版)》请在冰点文库上搜索。

第十五章Java反射机制与正则表达式.docx

第十五章Java反射机制与正则表达式

第十五章Java反射机制与正则表达式

学习目标

Ø理解Java反射机制的概念。

Ø能够上机对Java反射机制类和方法进行操作。

Ø掌握Java反射机制在远程调用中的控制。

课前准备

Ø掌握Java关于类与方法的概念与应用。

Ø了解代理模式。

 

15.1本章简介

反射的概念主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。

这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。

Java反射机制主要提供了以下功能:

●在运行时判断任意一个对象所属的类;

●在运行时构造任意一个类的对象;

●在运行时判断任意一个类所具有的成员变量和方法;

●在运行时调用任意一个对象的方法;

●生成动态代理。

本章首先介绍了JavaReflectionAPI的用法,然后介绍了一个远程方法调用的例子,在这个例子中客户端能够远程调用服务器端的一个对象的方法。

服务器端采用了反射机制提供的动态调用方法的功能,而客户端则采用了反射机制提供的动态代理功能。

15.2JavaReflectionAPI简介

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。

●Class类:

代表一个类。

●Field类:

代表类的成员变量(成员变量也称为类的属性)。

●Method类:

代表类的方法。

●Constructor类:

代表类的构造方法。

●Array类:

提供了动态创建数组,以及访问数组元素的静态方法。

如代码15-1所示DumpMethods类演示了ReflectionAPI的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息:

代码15-1DumpMethods.java

importjava.lang.reflect.*;

publicclassDumpMethods{

publicstaticvoidmain(Stringargs[])throwsException{

//加载并初始化命令行参数指定的类

ClassclassType=Class.forName(args[0]);

//获得类的所有方法

Methodmethods[]=classType.getDeclaredMethods();

for(inti=0;i

System.out.println(methods[i].toString());

}

}

运行命令"javaDumpMethodsjava.util.Stack",就会显示java.util.Stack类所具有的方法,程序的打印结果如下:

publicsynchronizedjava.lang.Objectjava.util.Stack.pop()

publicjava.lang.Objectjava.util.Stack.push(java.lang.Object)

publicbooleanjava.util.Stack.empty()

publicsynchronizedjava.lang.Objectjava.util.Stack.peek()

publicsynchronizedintjava.util.Stack.search(java.lang.Object)

如代码15-2所示ReflectTester类进一步演示了ReflectionAPI的基本使用方法。

ReflectTester类有一个copy(Objectobject)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性复制到新建的对象中,并将它返回。

这个例子只能复制简单的JavaBean,假定JavaBean的每个属性都有public类型的getXXX()和setXXX()方法。

代码15-2ReflectTester.java

importjava.lang.reflect.*;

publicclassReflectTester{

publicObjectcopy(Objectobject)throwsException{

//获得对象的类型

ClassclassType=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)new

ReflectTester().copy(customer);

System.out.println("Copyinformation:

"+customerCopy.getName()+"+"+

customerCopy.getAge());

}

}

classCustomer{//Customer类是一个JavaBean

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;}

}

ReflectTester类的copy(Objectobject)方法依次执行以下步骤。

(1)获得对象的类型:

ClassclassType=object.getClass();

System.out.println("Class:

"+classType.getName());

在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。

Class类是ReflectionAPI中的核心类,它有以下方法。

●getName():

获得类的完整名字。

●getFields():

获得类的public类型的属性。

●getDeclaredFields():

获得类的所有属性。

●getMethods():

获得类的public类型的方法。

●getDeclaredMethods():

获得类的所有方法。

●getMethod(Stringname,Class[]parameterTypes):

获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。

●getConstrutors():

获得类的public类型的构造方法。

●getConstrutor(Class[]parameterTypes):

获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

●newInstance():

通过类的不带参数的构造方法创建这个类的一个对象。

(2)通过默认构造方法创建一个新的对象:

ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{});

以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。

(3)获得对象的所有属性:

Fieldfields[]=classType.getDeclaredFields();

Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性。

(4)获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性复制到新的对象中:

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});

}

Method类的invoke(Objectobj,Objectargs[])方法用于动态执行一个对象的特定方法,它的第一个obj参数指定具有该方法的对象,第二个args参数指定向该方法传递的参数。

如代码15-3所示的InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法。

代码15-3InvokeTester.java

importjava.lang.reflect.*;

publicclassInvokeTester{

publicintadd(intparam1,intparam2){

returnparam1+param2;

}

publicStringecho(Stringmsg){

return"echo:

"+msg;

}

publicstaticvoidmain(String[]args)throwsException{

ClassclassType=InvokeTester.class;

ObjectinvokeTester=classType.newInstance();

//调用InvokeTester对象的add()方法

MethodaddMethod=classType.getMethod

("add",newClass[]{int.class,int.class});

Objectresult=addMethod.invoke(invokeTester,

newObject[]{newInteger(100),newInteger(200)});

System.out.println((Integer)result);

//调用InvokeTester对象的echo()方法

MethodechoMethod=classType.getMethod

("echo",newClass[]{String.class});

result=echoMethod.invoke(invokeTester,newObject[]{"Hello"});

System.out.println((String)result);

}

}

add()方法的两个参数为int类型,获得表示add()方法的Method对象的代码如下:

MethodaddMethod=classType.getMethod("add",newClass[]{int.class,int.class});

Method类的invoke(Objectobj,Objectargs[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。

invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。

在本例中,尽管InvokeTester类的add()方法的两个参数及返回值都是int类型,调用addMethod对象的invoke()方法时,只能传递Integer类型的参数,并且invoke()方法的返回类型也是Integer类型,Integer类是int基本类型的包装类:

Objectresult=addMethod.invoke(invokeTester,

newObject[]{newInteger(100),newInteger(200)});

System.out.println((Integer)result);//result为Integer类型

java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。

如代码15-4所示的ArrayTester1类的main()方法创建了一个长度为10的字符串数组,接着把索引位置为5的元素设为"hello",然后再读取索引位置为5的元素的值。

代码15-4ArrayTester1.java

importjava.lang.reflect.*;

publicclassArrayTester1{

publicstaticvoidmain(Stringargs[])throwsException{

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

//创建一个长度为10的字符串数组

Objectarray=Array.newInstance(classType,10);

//把索引位置为5的元素设为"hello"

Array.set(array,5,"hello");

//读取索引位置为5的元素的值

Strings=(String)Array.get(array,5);

System.out.println(s);

}

}

如代码15-5所示的ArrayTester2类的main()方法创建了一个5×10×15的整型数组,并把索引位置为[3][5][10]的元素的值为设37。

代码15-5ArrayTester2.java

importjava.lang.reflect.*;

publicclassArrayTester2{

publicstaticvoidmain(Stringargs[]){

intdims[]=newint[]{5,10,15};

Objectarray=Array.newInstance(Integer.TYPE,dims);

//使arrayObj引用array[3]

ObjectarrayObj=Array.get(array,3);

Classcls=arrayObj.getClass().getComponentType();

System.out.println(cls);

//使arrayObj引用array[3][5]

arrayObj=Array.get(arrayObj,5);

//把元素array[3][5][10]设为37

Array.setInt(arrayObj,10,37);

intarrayCast[][][]=(int[][][])array;

System.out.println(arrayCast[3][5][10]);

}

}

15.3在远程方法调用中运用反射机制

假定在SimpleServer服务器端创建了一个HelloServiceImpl对象,它具有getTime()和echo()方法。

HelloServiceImpl类实现了HelloService接口。

如代码15-6和代码15-7所示分别是HelloService接口和HelloServiceImpl类的源程序。

代码15-6HelloService.java

packageremotecall;

importjava.util.Date;

publicinterfaceHelloService{

publicStringecho(Stringmsg);

publicDategetTime();

}

代码15-7HelloServiceImpl.java

packageremotecall;

importjava.util.Date;

publicclassHelloServiceImplimplementsHelloService{

publicStringecho(Stringmsg){

return"echo:

"+msg;

}

publicDategetTime(){

returnnewDate();

}

}

SimpleClient客户端需要把调用的方法名、方法参数类型、方法参数值,以及方法所属的类名或接口名发送给SimpleServer,SimpleServer再调用相关对象的方法,然后把方法的返回值发送给SimpleClient。

为了便于按照面向对象的方式来处理客户端与服务器端的通信,可以把它们发送的信息用Call类(如代码15-8所示)来表示。

一个Call对象表示客户端发起的一个远程调用,它包括调用的类名或接口名、方法名、方法参数类型、方法参数值和方法执行结果。

代码15-8Call.java

packageremotecall;

importjava.io.*;

publicclassCallimplementsSerializable{

privateStringclassName;//表示类名或接口名

privateStringmethodName;//表示方法名

privateClass[]paramTypes;//表示方法参数类型

privateObject[]params;//表示方法参数值

//表示方法的执行结果

//如果方法正常执行,则result为方法返回值,如果方法抛出异常,那么result为该异常。

privateObjectresult;

publicCall(){}

publicCall(StringclassN

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2