欲生成對象實(shí)體,在Reflection 動(dòng)態(tài)機(jī)制中有兩種作法,一個(gè)針對“無自變量ctor”,一個(gè)針對“帶參數(shù)ctor”。如果欲調(diào)用的是“帶參數(shù)ctor“就比較麻煩些,不再調(diào)用Class的newInstance(),而是調(diào)用Constructor 的newInstance()。首先準(zhǔn)備一個(gè)Class[]做為ctor的參數(shù)類型,然后以此為自變量調(diào)用getConstructor(),獲得一個(gè)專屬ctor。接下來再準(zhǔn)備一個(gè)Object[] 做為ctor實(shí)參值,調(diào)用上述專屬ctor的newInstance()。
下面做個(gè)例子,該例子的反射對象沒有構(gòu)造方法(實(shí)際上是默認(rèn)的構(gòu)造方法),無自變量,動(dòng)態(tài)生成“Class object 所對應(yīng)之class”的對象實(shí)體,代碼如下:
首先建立com.lansin.ghk包,在其下建立兩個(gè)類:Person.java和Test1.java。
package com.lansin.ghk;public class Person{private String name;private String address;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "名稱為" + this.getName() + ", 地址為" + this.getAddress();}}
package com.lansin.ghk;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Test1 {public static void main(String[] args) throws Exception {Class<?> classType = Class.forName("com.lansin.ghk.Person");Object obj = null;obj = classType.newInstance();Field fields[] = classType.getDeclaredFields();for(int i=0; i<fields.length;i++){Field field = fields[i];String fieldName = field.getName();String firstLetter = fieldName.substring(0, 1).toUpperCase();String getMethodName = "get" + firstLetter + fieldName.substring(1);String setMethodName = "set" + firstLetter + fieldName.substring(1);Method getMethod = classType.getMethod(getMethodName);Method setMethod = classType.getMethod(setMethodName,field.getType());if("name".equals(fieldName)){setMethod.invoke(obj, "邁克·泰森");}else if("address".equals(fieldName)){setMethod.invoke(obj, "美國");}}System.out.println(obj);}}
運(yùn)行結(jié)果為:“名稱為邁克·泰森, 地址為美國”。
下面做個(gè)例子,該例子的反射對象包含構(gòu)造方法,有自變量,動(dòng)態(tài)生成“Class object 所對應(yīng)之class”的對象實(shí)體,代碼如下:
有構(gòu)造方法的Person類只需在上面的Person類里加一個(gè)構(gòu)造方法;Test2類“反射”Person。
package com.lansin.ghk;public class Person{private String name;private String address;public Person(String name, String address){this.name = name;this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "名稱為" + this.getName() + ", 地址為" + this.getAddress();}}
package com.lansin.ghk;import java.lang.reflect.Constructor;public class Test2 {public static void main(String[] args) throws Exception {Class<?> c = Class.forName("com.lansin.ghk.Person");Class[] pTypes = new Class[]{String.class, String.class};Constructor ctor = c.getConstructor(pTypes);Object obj = null;Object[] arg = new Object[]{"邁克·泰森", "美國"};obj = ctor.newInstance(arg);System.out.println(obj);}}
運(yùn)行,和上個(gè)程序結(jié)果一樣:“名稱為邁克·泰森, 地址為美國”。
比較上面兩段程序:首先要提供一個(gè)對象類的地址全稱(包名+類名)。
(一)對于沒有構(gòu)造函數(shù)的類,在運(yùn)行時(shí)刻創(chuàng)建該對象所屬類的對象實(shí)例:
先聲明一個(gè)泛型Class,
Class<?> classType = Class.forName("com.lansin.ghk.Person");
然后由泛型對象classType生成實(shí)例,
Object obj = classType.newInstance();
接下來調(diào)用反射機(jī)制提供的各種方法進(jìn)行動(dòng)態(tài)處理;
(二)對于有構(gòu)造函數(shù)的類,在運(yùn)行時(shí)刻創(chuàng)建該對象所屬類的對象實(shí)例:
同樣要先聲明一個(gè)泛型Class,
Class<?> classType = Class.forName("com.lansin.ghk.Person");
創(chuàng)建一個(gè)“類型類”集合,因?yàn)镻erson類的構(gòu)造函數(shù)有兩個(gè)string類型的形參,
Class[] pTypes = new Class[]{String.class, String.class};
接下來由生成的“由對象在運(yùn)行時(shí)所生成所屬類的對象”來創(chuàng)建一個(gè)帶有形參(是個(gè)集合)的構(gòu)造器,
Constructor ctor = classType .getConstructor(pTypes);
最后由構(gòu)造器生成一個(gè)實(shí)例對象,但是首先要設(shè)定實(shí)參,
設(shè)定實(shí)參:Object[] arg = new Object[]{"邁克·泰森", "美國"};
實(shí)例化對象:Object obj = ctor.newInstance(arg);
OK了。
其實(shí)到這里我還有很多細(xì)節(jié)沒有說,這個(gè)要在以后的工作中多多學(xué)習(xí),多多參考文檔,java api是個(gè)好東西。
下面的例子是在運(yùn)行時(shí)調(diào)用Method,代碼如下:
public class InvokeTester {public int add(int param1, int param2) {return param1 + param2;}public String echo(String msg) {return "echo: " + msg;}public static void main(String[] args) throws Exception {Class<?> classType = InvokeTester.class;Object invokeTester = classType.newInstance();// 調(diào)用InvokeTester對象的add()方法Method addMethod = classType.getMethod("add", new Class[] { int.class,int.class });Object result = addMethod.invoke(invokeTester, new Object[] {new Integer(100), new Integer(200) });System.out.println((Integer) result);// 調(diào)用InvokeTester對象的echo()方法Method echoMethod = classType.getMethod("echo",new Class[] { String.class });result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });System.out.println((String) result);}}
這個(gè)動(dòng)作和上述調(diào)用“帶參數(shù)之ctor”相當(dāng)類似。首先準(zhǔn)備一個(gè)Class[]做為參數(shù)類型(本例指定其中一個(gè)是String,另一個(gè)是Hashtable),然后以此為自變量調(diào)用getMethod(),獲得特定的Method object。接下來準(zhǔn)備一個(gè)Object[]放置自變量,然后調(diào)用上述所得之特定Method object的invoke()。
為什么獲得Method object時(shí)不需指定回返類型?
因?yàn)閙ethod overloading機(jī)制要求signature必須唯一,而回返類型并非signature的一個(gè)成份。換句話說,只要指定了method名稱和參數(shù)列,就一定指出了一個(gè)獨(dú)一無二的method。
下面的類是運(yùn)行時(shí)變更Field的內(nèi)容,比較簡單,代碼如下:
package com.lansin.ghk;import java.lang.reflect.Field;public class TestField {public double d;public static void main(String[] args) throws Exception {Class c = Class.forName("com.lansin.ghk.TestField");Field f = c.getField("d");TestField obj = new TestField();System.out.println("d= " + (Double)f.get(obj));f.set(obj, 12.34);System.out.println("d= " + obj.d);}}
與先前兩個(gè)動(dòng)作相比,“變更field內(nèi)容”輕松多了,因?yàn)樗恍枰獏?shù)和自變量。首先調(diào)用Class的getField()并指定field名稱。獲得特定的Field object之后便可直接調(diào)用Field的get()和set()。
聯(lián)系客服