java对象的类型转换_Java对象的类型转换和属性复制

1. 问题的源由

在J2EE项目开发中,会涉及很多领域模型对象,例如,

VO (View Object) 视图对象,也叫展示对象,用于前端页面渲染所需要的数据

DTO (Data Transfer Object) 数据传输对象,一般用于Service和Manager向外传输数据

PO (Persistent Object) 持久化对象,一般和数据库表结构会形成一一映射关系,通过DAO层向上传输数据源对象

更多领域分层模型,及其所在的应用分层,可见阿里巴巴Java开发手册中的工程规约定义。

这些VO/DTO/PO都是POJO对象,每个属性都有getter/setter方法的定义,其数据转换链条大概为,

数据库DB 》PO 》DTO 》VO

可以看到,在项目中不同的应用分层DB/DAO/Service/Manager/Web,经常会需要把一个数据对象转换为其它类型的数据对象,转换的同时复制部分对象属性,有时部分属性需要从多个数据对象获取进行组装。这些数据的转换有一个共同的需求,那就是从一个源对象变为目标对象

源对象 Source s 》目标对象 Target t

接下来我们就需要讨论这个转换过程。

2. 单个对象的转换

1)简单的Java对象转换,使用BeanUtils.copyProperties

使用Spring都知道Spring Beans中提供了一个BeanUtils,可以用于对象的属性复制,其使用方法为,

Target t = new Target();

BeanUtils.copyProperties(s, t);

BeanUtils.copyProperties(s, t, 'password');

其中,第二个copyProperties方法中第三个参数是告知复制过程中忽略复制'password'这个属性。

2)单个对象的转换,指定目标类

BeanUtils.copyProperties不提供目标对象的创建,因此每次都需要new出一个目标对象。为了能够省去这一步,可以使用下面的方法。

实现代码

public static T convert(S s, Class clazz) {

T t = null;

try {

t = clazz.newInstance();

BeanUtils.copyProperties(s, t);

} catch (Exception e) {

e.printStackTrace();

}

return t;

}

上述方法将对象的生成封装起来返回。

使用样例

Target t = convert(s, Target.class);

使用中直接指定目标类,代码更加简洁易懂。

3. List/Set集合之间的转换

在很多时候,我们不仅处理一个对象的转换,而是面对集合的对象,这时需要能够对集合中的对象进行批量处理转换。

1)List集合转换,将列表中每一个实体转换为目标类

实现代码

public static List convert(Iterable iterable, Class clazz) {

return StreamSupport.stream(iterable.spliterator(), false)

.map(s -> convert(s, clazz))

.collect(Collectors.toList());

}

使用样例

List targets = convert(srcCollection, Target.class);

2)List集合转换,提供一个mapper转换方法,将列表中每一个实体对象转换为目标类

实现代码

public static List convert(Iterable iterable,

Function super S, ? extends T> mapper) {

return StreamSupport.stream(iterable.spliterator(), false)

.map(mapper)

.collect(Collectors.toList());

}

使用样例

List targets = convert(srcCollection, mapper);

其中mapper的定义为Function super S, ? extends T>,即该函数需要一个源对象作为输入参数,返回一个目标对象

3)List集合转换,转换为指定的List/Set容器类,集合中的实体对象不变

实现代码

public static > U collect(Iterable iterable, CollectionFactory factory) {

U collection = factory.createCollection();

iterable.forEach(collection::add);

return collection;

}

其中CollectionFactory为一个集合类工厂。

使用样例

Iterable iterable = IntStream.range(0, 5).boxed().collect(Collectors.toList());

ArrayList arrayList = collect(iterable, ArrayList::new);

HashSet hashSet = collect(iterable, HashSet::new);

LinkedList linkedList = collect(iterable, LinkedList::new);

上述将一个Collection集合转换为ArrayList/HashSet/LinkedList,集合中的整型变量对象保持不变。

4)List集合转换,转换为指定的List/Set容器类,并将集合中的实体对象转换为目标类

实现代码

public static , T> U collect(Iterable iterable, Class clazz, CollectionFactory factory) {

Iterable list = convert(iterable, clazz);

U collection = factory.createCollection();

list.forEach(collection::add);

return collection;

}

使用样例

Iterable users = UserDao.SingleInstance.findAll();

ArrayList arrayList = collect(users, UserVO.class, ArrayList::new);

HashSet hashSet = collect(users, UserVO.class, HashSet::new);

LinkedList linkedList = collect(users, UserVO.class, LinkedList::new);

上述将一个Collection集合转换为ArrayList/HashSet/LinkedList,同时集合中的UserEntity变量对象转换为了UserVO。

4. List/Set/Map之间的转换

Java中Map的处理效率比List/Set高效不少,有些时候需要在List/Set/Map之间进行转换。

1)List集合转换,转换为Map集合,提供一个keyGenerator生成key,实体对象保存为value

实现代码

public static Map map(Iterable iterable, Function super S, String> keyGenerator) {

return StreamSupport.stream(iterable.spliterator(), false)

.collect(Collectors.toMap(keyGenerator, Function.identity()));

}

使用样例

List users = UserDao.SingleInstance.findAll();

Map result = map(users, UserEntity::getName);

上述样例中由UserEntity::getName来生成对象的键值,其必须为保证唯一。

2)Map集合转换,转换为List集合,实体对象保持不变

实现代码

public static > U collect(Map map, CollectionFactory factory) {

U collection = factory.createCollection();

map.values().iterator().forEachRemaining(collection::add);

return collection;

}

使用样例

Map users;

List list1 = collect(users, ArrayList::new);

Set set = collect(users, HashSet::new);

List list2 = collect(users, LinkedList::new);

Collection collection = users.values();

上述将一个用户的Map集合转换为List集合,可以看到一个简单获得List集合的方法就是使用map.values()方法。

3)Map集合转换,转换为指定的Map容器类

实现代码

public static > U map(Map srcMap, Class clazz, MapFactory factory) {

U u = factory.createMap();

srcMap.entrySet()

.forEach(ksEntry -> u.put(ksEntry.getKey(),

convert(ksEntry.getValue(), clazz)));

return u;

}

使用样例

Map users;

Map m1 = map(users, UserVO.class, HashMap::new);

Map m2 = map(users, UserVO.class, LinkedHashMap::new);

Hashtable m3 = map(users, UserVO.class, Hashtable::new);

上述将一个用户的Map集合转换为List集合,可以看到一个简单获得List集合的方法就是使用map.values()方法。

5. 源代码

演示代码仓库地址:https://gitee.com/pphh/blog,可以通过如下git clone命令获取仓库代码,

git clone git@gitee.com:pphh/blog.git

本篇博文的程序代码样例在文件路径171201_java_object_copy\171201_java_object_copy_convert中,请使用JDK8及后续版本编译并运行项目代码。

6. 参考资料

POJO阿里巴巴Java开发手册(2017版本):应用分层和领域模型PO/DTO/VO

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值