调用get/set方法
1.前提
在开发工作中遇到一个开发任务,将页面中的财务指标数据保存到数据库,具体机构如下图,并且表中字段有可能随着时间变化而变动。很显然这个时候创建表对象,并实现get/set方法取值/存值这种 硬编码的方式不能适用当前场景。用反射的方法实现,可以减少代码量,提高代码灵活性。
2.方法名拼接
TestModel.java
package Reflect;
public class TestModel {
private String name;
private int age;
private String school;
private boolean flag;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public boolean isFlag() {
return isFlag;
}
public void setFlag(boolean flag) {
isFlag = flag;
}
}
TestMain.java
package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class TestMain {
public static void main(String[] arg){
TestModel testModel = new TestModel();
try {
reflectProperty(testModel,"set");
List<String> data = (TestModel)reflectProperty(testModel,"get");
for(String dataValue : data){
System.out.println(dataValue);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object reflectProperty(Object model,String methodType) throws Exception {
Field[] field = model.getClass().getDeclaredFields();
// 获取属性的名字
String[] modelName = new String[field.length];
String[] modelType = new String[field.length];
List<String> data = new ArrayList<>();
List<String> types = new ArrayList<>();
for (int i = 0; i < field.length; i++) {
// 获取属性的名字
String name = field[i].getName();
System.out.println("打印传入类型的属性列表:"+name);
modelName[i] = name;
// 获取属性类型
String type = field[i].getGenericType().toString();
modelType[i] = type;
types.add(name);
//关键。。。可访问私有变量
field[i].setAccessible(true);
if (type.equals("class java.lang.String")) {
// 如果type是类类型,则前面包含"class ",后面跟类名
name = upperCase(name);
if("get".equals(methodType)){
Method getMet = model.getClass().getMethod(methodType + name);
// 调用getter方法获取属性值
String value = (String) getMet.invoke(model);
if (value == null) {
value = "";
}
data.add(value);
}
if("set".equals(methodType)){
Method setMet = model.getClass().getMethod(methodType+name,field[i].getType());
setMet.invoke(model, "test");
}
}
}
return data;
}
public static String upperCase(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
}
结果输出
方法总结:
虽然反射的性能不是很好,但是相比较于硬编码的不易扩展,getDeclareFields可以拿到所有的成员变量,后续添加或删除成员变量时,不用修改代码。
但是生成的get/set方法并不是只有已get/set开头的,而是以is开头的,比如boolean类型的成员变量。这个时候我们就需要去判断属性的类型,然后用不同的前缀来拼接get/set方法名,如下图给出的样例,ifFlag,就不能直接用get+fildName进行拼接
3.使用JDK工具类
Introspector和PropertyDescriptor 使用这两个工具类进行构造get、set方法。
输出:
方法总结:
相比用java反射获取的方法,使用工具类更加的通用,但是这两种方法都有一个通病,需要判断入参和返回的参数类型然后进行类型转换,这就要求你预判出所有可能的入参和返回值的类型,然后就行代码转化。