- 在通过反射获得某个类对应的Class对象之后,可以通过Class对象的getMethods()或者getMethod()来获得全部的方法或者某一个指定的方法,前者将返回Method数组,后者将返回单一的Method对象。
- 每个Method方法都包含一个invoke()方法,它的运行机制是,method对象.invoke(运行该method对象的类的实例化, 该method对象的参数)
- 这个程序的运行机制如下:
- 遍历配置文件,将键值对都加载到Properties的一个对象中
- 遍历Properties对象,如果键中不包含百分号,就认为是创建对象的键值对,创建出对象的对象,从而形成一个具有“字符串-实际对象”的对象池
- 再次遍历Properties对象,如果键中包含百分号,再执行对应的修改参数的操作
- 以下为代码,具体的讲解穿插在代码中extObj.txt的内容为
a=javax.swing.JFrame b=javax.swing.JLabel #set the title of a a%title=Test Title
package Chapter_4; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Properties; public class ExtendeObjectPoolFactory { private Map<String, Object> objectPool = new HashMap<>(); // 定义一个对象池,前面是对象名,后面是实际对象 private Properties config = new Properties(); // 从指定属性文件中初始化Properties对象 public void init(String fileName){ try(FileInputStream fis = new FileInputStream(fileName)){ config.load(fis); }catch (IOException exception){ System.out.println("读取" + fileName + "异常"); } } // 定义一个创建对象的方法,传入的是一个字符串(当作类名使用),程序可以根据该类名生成java对象 private Object createObject(String clazzName) throws InstantiationException, IllegalAccessException, ClassNotFoundException{ Class<?> clazz = Class.forName(clazzName); // 使用forName方法来创建Class对象(也就是类对应的Class对象) return clazz.newInstance(); // 创建该类的对象 } // 根据配置文件来创建对象,也就是初始化对象池 public void initPool() throws InstantiationException, IllegalAccessException, ClassNotFoundException{ for (String name : config.stringPropertyNames()){ // 每取出一个key-value对,如果key中不包括百分号,就表明是根据value来创建一个对象 if(!name.contains("%")){ objectPool.put(name, createObject(config.getProperty(name))); } } } // 通过指定文件来初始化对象池,它会根据配置文件来创建对象 public void initProperty() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException{ for(String name : config.stringPropertyNames()){ // 如果key中包括百分号,就认为这个key是用来为这个对象的成员变量设置值,百分号前为对象名,百分号后为成员变量名 // 程序将调用对应的setter方法来设置值 if(name.contains("%")){ String[] objAndProp = name.split("%"); // 将配置文件中的key按百分号分割 Object target = getObject(objAndProp[0]); // 取出需要设置成员变量值的目标对象 String mtdName = "set" + objAndProp[1].substring(0,1).toUpperCase() + objAndProp[1].substring(1); // 该成员变量的设置方法:set + "属性的首字母大写" + 剩下部分 Class<?> targetClass = target.getClass(); // 通过getClass方法获得对象对用的类 Method mtd = targetClass.getMethod(mtdName, String.class); // 获取该属性对应的setter方法 mtd.invoke(target, config.getProperty(name)); // 将config.getProperty(name)的属性值作为调用setter的实参 } } } public Object getObject(String name){ return objectPool.get(name); // 从对象池中取出指定name对应的对象 } public static void main(String args[]) throws Exception{ ExtendeObjectPoolFactory epf = new ExtendeObjectPoolFactory(); epf.init("extObj.txt"); epf.initPool(); epf.initProperty(); System.out.println(epf.getObject("a")); } } //运行这个程序,看到以下运行结果 // 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]
这是我看李刚编著的《疯狂Java讲义》后总结出来的。
java反射(3)调用方法
最新推荐文章于 2023-06-10 09:00:00 发布