专栏首页Java全栈使用泛型制作CopyUtil封装BeanUtils

使用泛型制作CopyUtil封装BeanUtils

Java泛型的实战应用

  • 1 泛型在框架中的使用
        • 1.1 集合框架中使用泛型
        • 1.2 fastjson框架中使用泛型
        • 1.3 泛型使用场景总结
  • 2 泛型的实战应用
        • 2.1 数据的存储使用泛型类
        • 2.2 参数的传递使用泛型方法
        • 2.3 总结

Java有很多的高级特性,泛型是其中之一,泛型即参数化类型。关于泛型的概念,有很多文章都有介绍,这里就不再过多的介绍了。本文将从实战的角度,来看看泛型在实际项目中的使用

1 泛型在框架中的使用

泛型在框架中及为常见,我们在使用各种框架的时候,都会使用到泛型,具体看下面的例子。

1.1 集合框架中使用泛型

这是最常见的泛型的使用场景,比如下面的代码

List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();

list1和list2虽然都是列表类型,但是列表里面存的数据可以是String,可以是Integer,也可以是自定义类型。集合中存放的数据,在定义的时候不能确定是什么类型,只有当使用集合时,才能确定放什么类型的数据。所以在集合的定义中,就用泛型来代表集合里面的数据。

1.2 fastjson框架中使用泛型

alibaba的fastjson很多人应该都用过,fastjson很多地方也用到了泛型,比如将json字符串转成对象,如下的例子

// 将userStr字符串映射成UserDto类
String userStr = "{id: '123', name: '张三'}";
UserDto userDto = JSON.parseObject(userStr, UserDto.class);

JSON类中,对parseObject方法的定义,如下

public static <T> T parseObject(String text, Class<T> clazz) {
    return parseObject(text, clazz);
}

parseObject方法中的参数传递用到了泛型,要把json字符串转成什么类,在定义的时候并不知道,只有在用到的时候,才知道具体的类型。

1.3 泛型使用场景总结

综合集合框架和JSON框架的例子,我们可以大概总结出泛型的使用场景,便于理解:不管是数据存储还是参数传递,定义的时候,类型并不确定,只有到使用的时候,才知道具体的类型。所以我们的项目中,如果有用到这种不确定类型的时候,就可以考虑泛型。

当然,泛型还有更多的使用场景,比如泛型接口,这里就不一一举例了。

2 泛型的实战应用

2.1 数据的存储使用泛型类

在实际项目开发中,有一种场景:前后端分离时,为了方便前后端的对接,一般会统一定义参数的传递格式和结果的返回格式。 以结果返回为例,一般都会定义【返回码】,【返回描述】,【返回数据】等,所以可以定义一个ResponseDto类,如下:

public class ResponseDto {
    /**
     * 返回码
     */
    private String code;

    /**
     * 返回信息
     */
    private String message;

    /**
     * 返回数据,???,应该定义成什么类型呢?
     */
    private ??? content;
	
	// 省略set get
	...
}

【返回码】一般是前后端约好的字符串类型,【返回描述】一般就是字符串类型,【返回数据】就不一定了,如果是查询类的请求,返回的数据就是列表信息,可能还包含分页信息;如果是保存、删除之类的请求,返回的数据可能是一条数据,也可能只是ID,也可能不需要返回数据。所以【返回数据】这个字段就是个不确定的类型,可以定义成泛型。所以我们就可以把ResponseDto类改成下面这样:

public class ResponseDto<T> {
    /**
     * 返回码
     */
    private String code;

    /**
     * 返回信息
     */
    private String message;

    /**
     * 返回数据
     */
    private T content;
}

使用的方法如下:

// 返回单个UserDto对象
ResponseDto<UserDto> responseDto = new ResponseDto<>();
responseDto.setContent(userDto); // userDto是已有的变量

// 返回UserDto列表
ResponseDto<List<UserDto>> responseDto = new ResponseDto<>();
responseDto.setContent(userDtoList); // userDtoList是已有的变量

// 返回ID
ResponseDto<String> responseDto = new ResponseDto<>();
responseDto.setContent(id); // id是已有的变量

这个类就叫做泛型类。

2.2 参数的传递使用泛型方法

以BeanUtils.copyProperties为例,大家应该对这个方法不陌生,就是将一个实体类中的属性值,拷贝到另一个实体类中。一般我们的使用方法是这样的:

// 功能:将UserDto数据拷贝到User
User user = new User();
BeanUtils.copyProperties(userDto, user); // userDto是已有的变量

但是每次都要写两行代码有点麻烦,要先new一个新的实体类,再往里面拷数据。于是我封装了个通用的工具类

public class CopyUtil {
    /**
     * CopyUtil.copy的定义很类似JSON.parseObject的定义
     */
    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) {
            e.printStackTrace();
        }
        BeanUtils.copyProperties(source, obj);
        return obj;
    }
}

同样是上面的例子,用工具类的写如下

User user = CopyUtil.copy(userDto, User.class); // userDto是已有的变量

CopyUtil.copy的定义很类似JSON.parseObject的定义。代码变成了一行,当然,减少一行也不足以将其封装成一个工具类。再来看一个场景,列表的拷贝,用BeanUtils.copyProperties的写法如下

// 功能:将List<UserDto>数据拷贝到List<User>
List<User> userList = new ArrayList<>();
// userDtoList是已有的变量
for (int i = 0, l = userDtoList.size(); i < l; i++) {
    UserDto userDto = userDtoList.get(i);
    User user = new User();
    BeanUtils.copyProperties(userDto, user);
    userList.add(user);
}

这样的代码量就比较多了,并且代码写法比较固定。如果项目中用到列表复制的功能比较多,那就有必要对其进行封装了,如下的copyList方法:

import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 甲蛙
 */
public class CopyUtil {

    /**
     * 列表复制
     */
    public static <T> List<T> copyList(List source, Class<T> clazz) {
        List<T> target = new ArrayList<>();
        if (!CollectionUtils.isEmpty(source)){
            if (!CollectionUtils.isEmpty(source)){
                for (Object c: source) {
                    T obj = copy(c, clazz);
                    target.add(obj);
                }
            }
        }
        return target;
    }

    /**
     * 单体复制
     */
    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) {
            e.printStackTrace();
        }
        BeanUtils.copyProperties(source, obj);
        return obj;
    }
}

用法很简单,还是以上面的列表复制为例,代码就变成这样:

// 功能:将List<UserDto>数据拷贝到List<User>
List<User> userList = CopyUtil.copyList(userDtoList, User.class);

封装成CopyUtil工具类后,不管是单体复制还是列表复制,都只需要一行代码,省去了大量的重复代码,从而提高开发效率,这里的copy方法和copyList方法,就是泛型方法,在方法的参数中使用了泛型。

当然这个工具类有个缺点,就是用到了反射,会牺牲一点性能,不过这点性能对于大部分的项目来说可以忽略不计。

2.3 总结

本文讨论了两种泛型的实战应用,一种是用来存储类型不确定的数据,用到泛型类;一种是用来传递类型不确定的参数,用到了泛型方法。当然,泛型还有更多的用法,比如泛型接口,比较典型的是比较器接口Comparable,这里就不再展开了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 自制CopyUtil优雅封装BeanUtils

    通常情况下,一个项目会有很多的分层,比如经典的三层controller, server, mapper(dao)

    甲蛙全栈
  • 工作中的设计模式 —— 原型模式

    原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。

    程序员小航
  • JavaWeb13-设计模式案例实现(Java真正的全栈开发)

    ? JavaWeb设计模式&案例 一.JavaWeb的设计模式 1. jsp模式介绍 SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一...

    Java帮帮
  • javaList集合的两种赋值方式

    在开发中难免会有entity,vo,dto之间的转换那么如何优雅快速的进行转换呢?当然你可以get在set显然不推荐这样做!

    许喜朝
  • BeanUtils开发包的使用

    对内省技术有了一定的了解之后,我们就可以来学习一下BeanUtils开发包的使用了。

    wangweijun
  • 字节流---复制文件和文件夹

    shimeath
  • Java泛型--BeanUtils.copyProperties引发的血案

    链接:https://www.toutiao.com/a6722037774528021003在一次使用BeanUtils.copyProperties的方法是...

    用户7886150
  • 用Spring的BeanUtils前,建议你先了解这几个坑!

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。根据注释,对方的SDK中写好的Request类有一个无...

    JAVA葵花宝典
  • java基础加强之内省

    黑泽君
  • Java程序员必会的工具库,让你代码量减少90%!

    工作很多年后,才发现有很多工具类库,可以大大简化代码量,提升开发效率,初级开发者却不知道。而这些类库早就成为了业界标准类库,大公司的内部也都在使用,如果刚工作的...

    Leetcode名企之路
  • Java必会的工具库,让你的代码量减少90%

    来源 | www.toutiao.com/i6943239541448917512

    好好学java
  • Java必会的工具库,让你的代码量减少90%

    来源 | www.toutiao.com/i6943239541448917512

    良月柒
  • Java必会的工具库,让你的代码量减少90%

    工作很多年后,才发现有很多工具类库,可以大大简化代码量,提升开发效率,初级开发者却不知道。而这些类库早就成为了业界标准类库,大公司的内部也都在使用,如果刚工作的...

    架构师修炼
  • 几个 BeanUtils 中的坑,千万别踩!

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。

    Java技术栈
  • Spring 的 BeanUtils 填坑记

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。

    Bug开发工程师
  • Spring 的 BeanUtils 的 copyProperties 方法需要注意的点

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。

    互扯程序
  • 用 Spring 的 BeanUtils 前,建议你先了解这几个坑!

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。根据注释,对方的SDK中写好的Request类有一个无...

    芋道源码
  • BeanUtils.copyProperties() 用法

    https://blog.csdn.net/jdjdndhj/article/details/62056137

    allsmallpig
  • 关于领域模型转换的那些事儿

    我们在软件开发设计及开发过程中,习惯将软件横向拆分为几个层。比如常见的三层架构:表现层(VIEW/UI)、业务逻辑层(SERVICE/BAL)、数据访问层(DA...

    端碗吹水

扫码关注云+社区

领取腾讯云代金券