一、场景说明
今天遇见一个很有意思的需求,读取文件一行数据(对应一个数据类对象),将这行数据导入数据库中。这本来是一个很简单且无聊的需求,不就是实例化一个数据类对象,然后导入数据库嘛。但是,但是!!!这行数据有五十个字段呀!!!这难道要让我手动调用五十次set方法吗?!(累死不说,写完估计会被技术总监骂死!!!)
二、通过反射机制获取类对象的所有属性以及相应的get、set方法
1、遍历类对象的所有属性
//可以使用getDeclaredFields()方法获取对象的所有属性
AutoClass autoClass = new AutoClass(); // 先初始化一个类
Field[] fields = autoClass.getClass().getDeclaredFields(); // 获取对象的所有属性
for (Field item : fields) {
String name = item.getName(); // 获取对象属性名
String typeName = item.getGenericType().getTypeName(); // 获取对象属性的类型
System.out.printf("属性名:%s,类型:%s\n", name, typeName);
}
2、获取属性的get、set方法
// 一般而言每个属性都有其get和set方法
// 通过方法名获取get方法
Method getMethod = autoClass.getClass().getMethod("getId");
// 调用get方法
String invoke = (String) getMethod.invoke(autoClass);
System.out.println(invoke);
// 通过方法名获取set方法,由于set方法是有参数的,所以这里也需要定义set方法的参数类型
Method setMethod = autoClass.getClass().getMethod("setId", String.class);
// 调用set方法
setMethod.invoke(autoClass, "gftz");
System.out.println(autoClass.getId());
// invoke方法中的autoClass表示autoClass这个指定对象调用相应方法
3、案例完整代码
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @description: 自动获取对象属性及方法
* @author: 黄珺瑜
* @create: 2022-07-07 21:02
**/
public class AutoClass {
private String id;
private int age;
private Date birthDate;
private boolean marriageStatus;
private BigDecimal salary;
public AutoClass() {
}
public AutoClass(String id, int age, Date birthDate, boolean marriageStatus, BigDecimal salary) {
this.id = id;
this.age = age;
this.birthDate = birthDate;
this.marriageStatus = marriageStatus;
this.salary = salary;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public boolean isMarriageStatus() {
return marriageStatus;
}
public void setMarriageStatus(boolean marriageStatus) {
this.marriageStatus = marriageStatus;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
@Override
public String toString() {
return "AutoClass{" +
"id='" + id + '\'' +
", age=" + age +
", birthDate=" + birthDate +
", marriageStatus=" + marriageStatus +
", salary=" + salary +
'}';
}
public static void main(String[] args) {
AutoClass autoClass = new AutoClass(
UUID.randomUUID().toString().replaceAll("-", ""),
18,
new Date(),
false,
new BigDecimal(888888.8)
);
Field[] fields = autoClass.getClass().getDeclaredFields();
try {
Method method = autoClass.getClass().getMethod("getId");
String invoke = (String) method.invoke(autoClass);
System.out.println(invoke);
System.out.println(autoClass.getId());
Method setMethod = autoClass.getClass().getMethod("setId", String.class);
setMethod.invoke(autoClass, "gftz");
System.out.println(autoClass.getId());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
for (Field item : fields) {
String name = item.getName();
String typeName = item.getGenericType().getTypeName();
System.out.printf("属性名:%s,类型:%s\n", name, typeName);
}
}
}
三、通过反射机制实现类对象的实例化
相信看完上面的讲解已经对如何通过反射机制获取类对象的属性及方法有了一定的了解,接下来将进入真正的实战阶段(由于开发的保密性,无法给出真实的案例,这里就用简化版的案例来说明一下)
1、工具类讲解
package utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
/**
* @description: 数据类的相关操作
* @author: 黄珺瑜
* @create: 2022-07-07 22:05
**/
// 由于为了让这个工具类能够通用,故而用了泛型,对其不了解需要自行百度一下。
public class ObjectOperate<T> {
/**
* 设置数据类对象的属性
* @param obj 数据类对象的实例
* @param name 属性名
* @param type 属性类型名
* @param val 需要存入的属性值
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void setValues(T obj, String name, String type, Object val) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = null;
// 通过属性类型来获取相应的方法以及强制转化属性值并初始化相应属性
// 这里考虑到了大部分常用的数据类型,可拿来即用。
switch (type){
case "int":
method = obj.getClass().getMethod(name, int.class);
method.invoke(obj,(int)val);
break;
case "short":
method = obj.getClass().getMethod(name, short.class);
method.invoke(obj,(short)val);
break;
case "long":
method = obj.getClass().getMethod(name, long.class);
method.invoke(obj,(long)val);
break;
case "float":
method = obj.getClass().getMethod(name, float.class);
method.invoke(obj,(float)val);
break;
case "double":
method = obj.getClass().getMethod(name, double.class);
method.invoke(obj,(double)val);
break;
case "boolean":
method = obj.getClass().getMethod(name, boolean.class);
method.invoke(obj,(boolean)val);
break;
case "java.lang.String":
method = obj.getClass().getMethod(name, String.class);
method.invoke(obj,(String)val);
break;
case "java.util.Date":
method = obj.getClass().getMethod(name, Date.class);
method.invoke(obj,(Date)val);
break;
case "java.math.BigDecimal":
method = obj.getClass().getMethod(name, BigDecimal.class);
method.invoke(obj,(BigDecimal)val);
break;
}
}
}
2、使用说明
// 模拟案例数据
List<Object> params = new ArrayList<>();
params.add(UUID.randomUUID().toString().replaceAll("-", ""));
params.add(18);
params.add(new Date());
params.add(false);
params.add(new BigDecimal(888888.8));
// 初始话类型操作的工具类
ObjectOperate<AutoClass> objectOperate = new ObjectOperate<>();
// AutoClass使用到上面的,故不再给出AutoClass类
AutoClass autoClass = new AutoClass();
Field[] fields = autoClass.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
String name = fields[i].getName(); // 属性名
// 设置为属性的set方法名,如:属性名为id,对应set方法名为setId
name = "set"+name.substring(0, 1).toUpperCase() + name.substring(1);
String typeName = fields[i].getGenericType().getTypeName(); //属性类型名
try {
objectOperate.setValues(autoClass,name,typeName,params.get(i)); // 初始化对象的属性
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
System.out.println(autoClass.toString());
希望这篇文章能解决你当前遇到的惨景!!!(佛祖保佑,永无bug,永不修改)
如果这篇文章对你有帮助请不要吝啬你点赞和收藏哦!!!