反射机制最大的特征就是可以根据其自身的特点(Object类直接操作、可以直接操作属性或方法)实现相同功能类的重复操作的抽象处理。
1、利用反射机制进行属性自动赋值的例子【单级属性赋值】:
package com.mydemo;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 保存要设置的属性内容
String value = "name:Kangkang|job:Student";
// 工具类自动设置
Emp emp = ClassInstanceFactory.create(Emp.class, value);
System.out.println("姓名:" + emp.getName() + "、职位:" + emp.getJob());
}
}
class Emp {
private String name;
private String job;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
class ClassInstanceFactory {
private ClassInstanceFactory() {
}
/**
* 实例化对象的创建方法,该对象可以根据传入的字符串结构:“属性:内容|属性:内容”
*
* @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @param <T>
* @return 一个已经配置好属性内容的Java类对象
*/
public static <T> T create(Class<?> clazz, String value) {
Object object = null;
try {
// 如果要想采用反射进行简单Java类对象属性设置的时候,类中必须有无参构造
object = clazz.getDeclaredConstructor().newInstance();
// 通过反射设置属性
BeanUtils.setValue(object, value);
// 返回对象
return (T) object;
} catch (Exception e) {
// 设置错误返回null
return null;
}
}
}
/**
* 需要通过属性找到setter方法,
* 所以需要提供有一个首字母大写的功能,
* 为此定义一个字符串工具类
*/
class StringUtils {
/**
* 实现字符串首字母大写,如果只有一个字母则直接将此字母大写
*
* @param string 要转换的字符串
* @return 大写处理结果,如果传入的字符串为空(包括空字符串)则返回null
*/
public static String initcap(String string) {
// 判断字符串是否为空,
if (string == null || "".equals(string)) {
// 为空则直接返回
return string;
}
// 判断字符串长度
if (string.length() == 1) {
// 单个字母直接大写
return string.toUpperCase();
} else {
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
}
}
/**
* 通过该类实现setter方法的调用并进行属性赋值(这里暂时先考虑String型属性)
*/
class BeanUtils {
public BeanUtils() {
}
/**
* 实现指定对象的属性设置
*
* @param object 要进行反射操作的实例化对象
* @param value 包含指定内容的字符串,格式为“属性:内容|属性:内容”
*/
public static void setValue(Object object, String value) {
// 按照“|”对每一组属性进行拆分
String results[] = value.split("\\|");
for (int i = 0; i < results.length; i++) {
// attval[0]保存的是属性名称,attval[1]保存的是属性内容
// 获取属性“名称”与“内容”
String attval[] = results[i].split(":");
try {
// 获取成员
Field field = object.getClass().getDeclaredField(attval[0]);
// 根据成员名称拼凑出要使用的setter方法内容,同时根据Field获取属性类型
// 该类型作为setter方法参数类型,这样就可以获取到正确的Method对象
Method method = object.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
// 调用setter方法设置内容
method.invoke(object, attval[1]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
运行结果:
姓名:Kangkang、职位:Student