标签:方法 setter 接收 运行时 世界 miss mapper 吐槽 应该
最近在写java代码的时候,需要进行对象转换,由于字段名存在不同,BeanUtils无法满足需求,所以想到了java世界有没有类似C#的AutoMapper库,找到了 ModelMapper
以官方的Getting Started为例
源对象
// Assume getters and setters on each class class Order { Customer customer; Address billingAddress; } class Customer { Name name; } class Name { String firstName; String lastName; } class Address { String street; String city; }
目标对象
// Assume getters and setters class OrderDTO { String customerFirstName; String customerLastName; String billingStreet; String billingCity; }
由于以上对象的定义符合约定的规则,可以不需要任何配置,完成类型的转换
ModelMapper modelMapper = new ModelMapper(); OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
重点来了,有时候我们需要转换的是整个List,总不至于让我们对列表中每个对象逐个进行转换,幸好,官方也提供了相应的api
ModelMapper modelMapper = new ModelMapper(); modelMapper.createTypeMap(Order.class, OrderDTO.class); List<Order> orderList = new ArrayList<>(); //TODO: orderList添加元素 Type listType = new TypeToken<List<OrderDTO>>(){}.getType(); List<OrderDTO> dtoList = modelMapper.map(orderList, listType);
看起来好像一切正常,程序运行出来的结果也是正确的,但是,细看最后一行代码
List<OrderDTO> dtoList = modelMapper.map(orderList, listType);
modelMapper.map方法接收的2个参数类型,一个是 List<Order>, 另外一个是 Type, 编译器无法在编译时刻知道Type中包含具体什么类型,它是怎么知道这个方法返回的类型是 List<OrderDTO>?于是我将这一行代码改成了
List<Order> dtoList = modelMapper.map(orderList, listType);
编译器没有警告和错误提示,运行时查看dtoList中对象的结构为OrderDTO,查看ModelMapper的源码,发现
public class ModelMapper { public <D> D map(Object source, Type destinationType){...}
从方法的签名上看,D的类型是无法确定的(虽然方法内部可以通过读取Type中包含的类型,构造出对象),也就是说,唯一能够确定的是方法返回的是Object,通过IDEA的智能提示,这个方法确实返回的是Object, 那么为什么将Object赋值给List对象的时候,编译器没有警告呢?
我们用java和C#对这种泛型写法做一个简单的对比测试
java代码
public class Mapper { public <D> D convert(Object obj) { return (D)obj; } }
C#代码
public class Mapper { public T convert(Object obj){ return (T)obj; } }
对java代码进行编译,顺利通过,相反,对C#的代码进行编译,未通过,有错误提示,“Error CS0246: The type or namespace name ‘T‘ could not be found (are you missing a using directive or an assembly reference?) (CS0246) ”,明确指出T的类型未找到,
从我个人的理解,java中的泛型由于运行时的类型擦除,只在编译时起到类型检查的作用,但是上述的写法做到了让编译器的类型检查失效,根本就不应该让这样的代码通过编译,编译器的语义分析存在缺陷。
另外吐槽一下java的类型书写,C#通过AutoMapper对列表的转换可以写成
List<OrderDTO> dtoList = mapper.map<List<OrderDTO>>(orderList);
但是java中没有List<OrderDTO>.class的写法,是很膈应的事情
由于刚从C#入java,理解会有偏差,欢迎指正
标签:方法 setter 接收 运行时 世界 miss mapper 吐槽 应该
原文地址:https://www.cnblogs.com/seamas/p/9344666.html