Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法;可以获取构造器,由Constructor对象表示,调用Constructor对象的newInstance方法可以执行类对应的构造方法;可以获取成员变量,由Field对象表示,通过Field对象可以直接修改类的成员变量的访问权限和值。

创建对象

通过反射有两种方式创建对象

使用Class对象的newInstance(),这是最常用的方式,根据配置文件信息创建对象。

使用Class对象获取指定的Constructor对象,再由Constructor对象的newInstance创建类的对象。

调用方法

首先要获取类在JVM中对应的Class对象,通过类的Class对象的getMethod方法来获取类的方法,返回Method类型的对象,最后通过Method对象的invoke来执行类的方法。

下面的例子将演示从配置文件中读取数据来动态地创建对象,还通过配置文件信息来执行对象的setter来初始化对象。

 1 package jvmTest;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.IOException;
 5 import java.lang.reflect.Method;
 6 import java.util.HashMap;
 7 import java.util.Map;
 8 import java.util.Properties;
 9 
10 public class ExtendedObjectPoolFactory {
11     private Map<String, Object> objectPool = new HashMap<>();
12     private Properties config = new Properties();
13     public void init(String fileName) {
14         try {
15             FileInputStream fis = new FileInputStream(fileName);
16             config.load(fis);
17         } catch (IOException ex) {
18             System.out.println("读取 " + fileName + " 异常");
19             ex.printStackTrace();
20         }
21     }
22     private Object createObject(String clazzName) throws Exception {
23         Class<?> clazz = Class.forName(clazzName);
24         //使用clazz默认构造器创建对象
25         return clazz.newInstance();
26     }
27     //根据配置文件创建对象
28     public void initPool() throws Exception {
29         for (String name : config.stringPropertyNames()) {
30             if (!name.contains("%")) {
31                 objectPool.put(name, createObject(config.getProperty(name)));
32             }
33         }
34     }
35     
36     //根据配置文件来执行对象对应的set方法
37     public void initProperty() throws Exception {
38         for (String name : config.stringPropertyNames()) {
39             if (name.contains("%")) {
40                 String[] objAndPro = name.split("%");
41                 //获取对象
42                 Object target = getObject(objAndPro[0]);
43                 //构造setter方法名
44                 String mtdName = "set"+ objAndPro[1].substring(0,1).toUpperCase() + objAndPro[1].substring(1);
45                 Class<?> targetClass = target.getClass();
46                 Method mtd = targetClass.getMethod(mtdName, String.class);
47                 mtd.invoke(target, config.getProperty(name));
48             }
49         }
50     }
51     
52     public Object getObject(String name) {
53         return objectPool.get(name);
54     }
55     
56     public static void main(String[] args) throws Exception {
57         ExtendedObjectPoolFactory epf = new ExtendedObjectPoolFactory();
58         epf.init("extObj.txt");
59         epf.initPool();
60         epf.initProperty();
61         System.out.println(epf.getObject("a"));
62     }
63 }

上面程序第23行获取Class对象后在第25行使用默认的构造器动态创建出了对象, 

如果要使用指定构造器,需要先获取Constructor对象,再使用Cronstructor对象的newInstance创建对象,像下面这样,

1 Constructor ctor = clazz.getConstructor(String.class);
2 return ctor.newInstance("here is parameter for specific constructor");

第45行获取Class对象后,在46行通过Class对象获取指定要执行的方法(带一个参数),用Method对象表示,最后在47行调用Method对象的invoke可以执行类的指定方法

上面的例子使用下面的测试文件进行测试,

extObj.txt

1 a=javax.swing.JFrame
2 b=javax.swing.JLabel
3 a%title=Test title

输入结果,

javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=Test title,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
View Code

相关文章: