從一段java泛型代碼發現java編譯器的缺陷

來源:互聯網
上載者:User

標籤:方法   setter   接收   運行時   世界   miss   mapper   吐槽   應該   

最近在寫java代碼的時候,需要進行對象轉換,由於欄位名存在不同,BeanUtils無法滿足需求,所以想到了java世界有沒有類似C#的AutoMapper庫,找到了 ModelMapper

以官方的Getting Started為例 

來源物件

// Assume getters and setters on each classclass Order {  Customer customer;  Address billingAddress;}class Customer {  Name name;}class Name {  String firstName;  String lastName;}class Address {  String street;  String city;}

  目標對象

// Assume getters and settersclass 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,理解會有偏差,歡迎指正

 

從一段java泛型代碼發現java編譯器的缺陷

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.