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