介绍
CopyUtil是一个通用的对象复制工具类,其中包含单体复制和列表复制两个方法。
单体复制方法copy通过传入源对象和目标class,利用Java反射机制创建目标对象,并将源对象的属性值复制到目标对象中。若源对象为空,则返回null。若创建目标对象失败,则返回null。
列表复制方法copyList通过遍历源列表中的每个对象,调用单体复制方法copy完成每个对象的复制,将复制后的对象添加到新的列表中。若源列表为空,则返回空列表。
在这个实现中,使用了开源框架BeanUtils的copyProperties方法实现属性复制。同时,为了处理异常情况,使用了try-catch语句进行异常捕获,并记录错误信息到日志系统中。代码中还引入了@Slf4j注解,方便使用Lombok提供的日志功能,无需手动声明Logger对象。
该工具类可用于简化程序中的对象复制操作,避免了手动编写属性赋值代码的繁琐过程,提高了开发效率。
注意的是,在使用BeanUtils进行属性复制时,源对象和目标对象的属性名、类型等必须严格一致,否则会导致复制失败或出现异常。
源码
@Slf4j
public class CopyUtil {
/**
* 单体复制
*/
public static <T> T copy(Object source, Class<T> clazz) {
if (source == null) {
return null;
}
T obj = null;
try {
obj = clazz.newInstance();
} catch (Exception e) {
log.error("CopyUtil error",e);
return null;
}
BeanUtils.copyProperties(source, obj);
return obj;
}
/**
* 列表复制
*/
public static <T> List<T> copyList(List<?> source, Class<T> clazz) {
List<T> target = new ArrayList<>();
if (!CollectionUtils.isEmpty(source)){
for (Object c: source) {
T obj = copy(c, clazz);
target.add(obj);
}
}
return target;
}
}
分析
这段代码实现了一个通用的对象复制工具类 CopyUtil,提供了单体复制和列表复制两个方法,下面分别对两个方法的作用进行分析:
- 单体复制方法 public static <T> T copy(Object source, Class<T> clazz):
该方法接收两个参数,源对象source和目标对象的Class类型clazz。它的作用是将源对象的属性值赋值给目标对象,并返回赋值后的目标对象。
具体实现过程如下:
- 首先进行空指针判断,如果源对象为空直接返回 null。
- 然后使用反射机制创建目标对象。
- 最后利用 BeanUtils.copyProperties 方法将源对象的属性值复制到目标对象中。
- 返回复制后的目标对象。
- 列表复制方法 public static <T> List<T> copyList(List<?> source, Class<T> clazz):
该方法接收两个参数,源列表 source 和目标对象的 Class 类型 clazz。它的作用是将源列表中所有对象的属性值复制给各自对应的目标对象,并返回赋值后的目标对象列表。
具体实现过程如下:
- 首先创建一个目标对象列表 target,并用ArrayList实例化。
- 接着进行非空判断,如果源列表不为空,遍历源列表中的每个对象。
- 每次循环调用单体复制方法 copy(c, clazz) 复制当前对象,得到复制后的目标对象obj,并将obj添加到目标对象列表中。
- 最后返回复制后的目标对象列表。
用例
单体复制用例:将 StudentDO 对象的属性通过 CopyUtil 对象复制工具类赋值给 StudnetVO 对象
StudentDO对象如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentDO {
/** 学号 */
private Long id;
/** 姓名 */
private String name;
/** 性别 */
private Integer sex;
/** 年龄 */
private Integer age;
/** 班级 */
private String className;
/** 专业 */
private String speciality;
/** 电话 */
private String phone;
/** 邮箱 */
private String email;
}
StudentVO 对象如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {
/** 学号 */
private Long id;
/** 姓名 */
private String name;
/** 性别 */
private Integer sex;
/** 年龄 */
private Integer age;
}
可以看出 StudentVO 对象的属性名和 StudentDO 对象属性名一模一样,两者的差别仅在属性个数上。
将 StudentDO 对象的属性通过 CopyUtil 对象复制工具类赋值给 StudnetVO 对象,通过输出可以看到对象属性赋值成功。
@SpringBootTest
class CodeUseCasesApplicationTests {
@Test
void copyTest () {
StudentDO studentDO = new StudentDO(Long.parseLong("202003021055"),"梁域强",1,21,"软件工程B班","软件工程","18475621348","542108996@qq.com");
StudentVO studentVO = CopyUtil.copy(studentDO, StudentVO.class);
System.out.println("studentDO = " + studentDO);
System.out.println("studentVO = " + studentVO);
}
}
输出结果:
列表复制用例:将 studentDOList 中的每一个属性通过 CopyUtil 对象复制工具类赋值给 studentDOList
@Test
void listCopy() {
StudentDO studentDO1 = new StudentDO(Long.parseLong("202003021057"),"张三",1,21,"软件工程B班","软件工程","18475621348","542108996@qq.com");
StudentDO studentDO2 = new StudentDO(Long.parseLong("202003021023"),"李四",1,20,"计科A班","计算机科学与技术","15362919370","1378538974@qq.com");
StudentDO studentDO3 = new StudentDO(Long.parseLong("202003021033"),"王五",0,24,"软件工程B班","软件工程","1382537649","6725368337@qq.com");
List<StudentDO> studentDOList = Arrays.asList(studentDO1,studentDO2,studentDO3);
List<StudentVO> studentVOList = CopyUtil.copyList(studentDOList, StudentVO.class);
System.out.println("studentDOList = " + studentDOList);
System.out.println("studentVOList = " + studentVOList);
}
输出结果: