Java反射实现通用编程
1. Java的反射应用 - 通用编程
实体类
public class User {
private Integer id;
private String name;
public User() {}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + '}';
}
}
1.1 反射执行任意实体类对象的 set 方法
public class TestReflectMethod {
public static void main(String[] args) throws Exception {
User user = new User();
setValue(user, "id", 10);
setValue(user, "name", "hello,world");
System.out.println(user); // User{id=10, name='hello,world'}
}
/**
* 给指定对象的指定属性设置指定值
* @param obj 指定的对象
* @param fieldName 指定的属性名
* @param value 指定的属性值
*/
public static void setValue(Object obj, String fieldName, Object value) throws Exception {
Class<?> objClass = obj.getClass();
// 根据小驼峰命名规范获取 set 方法名,eg: setName
String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
System.out.println(methodName);
Field field = objClass.getDeclaredField(fieldName);
// 获取到属性类型
Class<?> fieldType = field.getType();
// 获取到 set 方法
Method method = objClass.getMethod(methodName, fieldType);
method.invoke(obj, value);
}
}
1.2 反射执行任意实体类对象的 get 方法
public class TestReflectMethodGet {
public static void main(String[] args) throws Exception {
/* 实体类的 set/get 方法通用调用示例 */
User user = new User(10, "小黑");
Object id = getValue(user, "id");
Object name = getValue(user, "name");
System.out.println(id + ":" + name); // 10:小黑
}
/**
* 从指定对象的指定属性获取属性值
* @param obj 指定对象
* @param fieldName 指定属性
* @return Object类型值
*/
public static Object getValue(Object obj, String fieldName) throws Exception {
Class<?> objClass = obj.getClass();
// 根据小驼峰命名规范获取 get 方法名,eg: getName
String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
// 获取到 get 方法
Method method = objClass.getDeclaredMethod(methodName, (Class<?>[]) null);
return method.invoke(obj, (Object[]) null);
}
}
1.3 反射执行任意实体类对象的任意方法
import java.lang.reflect.Method;
public class TestInvokeAnything {
public static void main(String[] args) throws Exception {
// invokeAny() 执行任何方法
// 传入:对象(Object)、方法名称(String)、形参(.class)、实参(Object)
invokeAny(
createObject("com.day.t1_factory.Student"),
"exam",
new Class[] {int.class, double.class, String.class},
2, 10, "小明"
); // public void exam(int n, double score, String name)
Object o = createObject("com.day.t1_factory.Student");
invokeAny(o, "study", null, null); // public void study()
invokeAny(o, "study", new Class[] {Integer.class}, 100); // public int study(Integer a)
}
/**
* 反射技术,执行任何方法
* @param obj Objcet类型对象
* @param methodName String类型方法名称
* @param types Class[]数组类型的types
* @param args Object类型的可变长参数
* @throws Exception
*/
public static void invokeAny(Object obj, String methodName, Class<?>[] types, Object...args) throws Exception {
Class<?> c = obj.getClass(); // 1.获取类对象
Method m = c.getDeclaredMethod(methodName, types); // 2.获得方法的对象Method
m.invoke(obj, args); // 3.执行方法
}
/**
* 反射技术,工厂设计模式
* @param className 类的全限定名
* @return 返回Object类型的对象
*/
public static Object createObject(String className) {
try {
Class<?> c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
1.4 读取配置文件反射创建任意实体对象
public class TestReflectConfigFile {
public static void main(String[] args) throws Exception {
User user = (User) getInstanceFromConfigFile("config.properties", "userClassName");
System.out.println(user);
}
/**
* 通过配置文件获取并创建指定键的类的实例对象
* @param fileName 配置文件名称
* @param key 配置文件中的键
* @return Object对象
*/
public static Object getInstanceFromConfigFile(String fileName, String key) throws Exception {
Properties properties = new Properties();
// 获取文件的 字节输入流
InputStream is = TestReflectConfigFile.class.getClassLoader().getResourceAsStream(fileName);
// 将流加载到 properties(map键值映射)
properties.load(is);
// 获取类全名
String className = properties.getProperty(key);
// 创建对象并返回
return Class.forName(className).newInstance();
}
}
/*
* config.properties 配置文件内容:
* userClassName=com.demo.reflect.User
*/