Class 对象可以获得该类里的方法(由 Method 对象表示)、构造器(由 Constructor 对象表示)、成员变量(由 Field 对象表示),这三个类都位于 java.lang.reflect 包下,并实现了 java.lang.reflect.Member 接口。程序可以通过对象来执行对应的方法,通过 Constructor 对象来调用对应的构造器创建实例,能通过 Field 对象直接访问并修改对象的成员变量值。
创建对象
通过反射来生成对象需要先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance() 方法来创建该 Class 对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。
在很多 Java EE 框架中都需要根据配置文件信息来创建 Java 对象,从配置文件读取的只是某个类的字符串类名,程序需要根据该字符串来创建对应的实例,就必须使用反射。
下面程序就实现了一个简单的对象池,该对象池会根据配置文件读取 key-value 对,然后创建这些对象,并将这些对象放入一个 HashMap 中。
public class ObjectPoolFactory {
// 定义一个对象池,前面是对象名,后面是实际对象
private Map objectPool = new HashMap<>();
// 定义一个创建对象的方法
// 该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象
private Object createObject(String clazzName) throws Exception, IllegalAccessException, ClassNotFoundException {
// 根据字符串来获取对应的Class对象
Class> clazz = Class.forName(clazzName);
// 使用clazz对应类的默认构造器创建实例
return clazz.getConstructor().newInstance();
}
// 该方法根据指定文件来初始化对象池
// 它会根据配置文件来创建对象
public void initPool(String fileName)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
try (FileInputStream fis = new FileInputStream(fileName)) {
Properties props = new Properties();
props.load(fis);
for (String name : props.stringPropertyNames()) {
// 每取出一对key-value对,就根据value创建一个对象
// 调用createObject()创建对象,并将对象添加到对象池中
objectPool.put(name, createObject(props.getProperty(name)));
}
} catch (Exception ex) {
System.out.println("读取" + fileName + "异常");
}
}
public Object getObject(String name) {
// 从objectPool中取出指定name对应的对象
return objectPool.get(name);
}
public static void main(String[] args) throws Exception {
ObjectPoolFactory pf = new ObjectPoolFactory();
pf.initPool("obj.txt");
System.out.println(pf.getObject("a")); // ①
System.out.println(pf.getObject("b")); // ②
}
}
上面程序中 createObject() 方法里的两行粗体字代码就是根据字符串来创建 Java 对象的关键代码,程序调用 Class 对象的 newInstance() 方法即可创建一个 Java 对象。程序中的 initPool() 方法会读取属性文件,对属性文件中每个 key-value 对创建一个 Java 对象,其中 value 是该 Java 对象的实现类,而 key 是该 Java 对象放入对象池中的名字。为该程序提供如下属性配置文件。
a=java.util.Date
b=javax.swing.JFrame
编译、运行上面的 ObjectPoolFactory 程序,执行到 main 方法中的①号代码处,将看到输出系统当前时间——这表明对象池中已经有了一个名为a的对象,该对象是一个 ja