• 静思
  • 吴言片语
    • 吴言
    • 片语
    • 杂七杂八
  • 死于青春
    • 一路走好
  • 乌合麒麟
  • 纪念
    • 5.12
    • 3.23
  • GitHub
    • A List of Post-mortems
    • The Art of Command Line
  • 关于
    • Privacy Policy

程序员的信仰

金鳞岂是池中物,一遇风云便化龙

HOME » 技术生活 » 有关Java泛型的类型擦除(type erasing)

有关Java泛型的类型擦除(type erasing)

2012 年 2 月 2 日 @ 下午 5:24 by Jay | 被踩了 7,383 脚

自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资。在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结论是

  • Java使用类型擦除(type erasing),泛型信息只在编译时供javac作类型检查用,在编译后便被javac擦除,因此无法被反射
  • C++使用代码模板实现泛型,即在预处理时会生成类似「list_int」,「list_char」等的泛型类,虽然解决Java的运行时伪泛型的问题,但是会导致编译后的代码呈线性增长
  • 于是在一般情况下,Java的类型擦除实现较优

这三条已经比绝大多数的Java培训讲师讲得深刻了。但是如果下面有人问「在什么情况下C++的实现方式较优」时,除了无法被反射,我很难现抓一个有说服力的例子。今天,Spring的RestTemplate终于给了我这个例子

我遇到的问题如下(阅读需要有一些Spring MVC、REST基础)

有一个返回类型为List的MVC方法:

@RequestMapping(value = "...", method = RequestMethod.GET)
@ResponseBody
public List doSomethingREST() {
    List domainObjs = ... ;
    return domainObjs;
}

在运行时,Spring MVC会将List转换成JSON字符串并返回至客户端。但是如果我在另一个service中使用RestTemplate直接调用该REST接口,问题便来了:

List domainObjs = this.restTemplate.getForObject(this.restURL, List.class);

关键在于第二个参数,是返回值的类型,RestTemplate会根据此类型选择适当的MessageConverter将调用REST接口的返回值反序列化为与类型匹配的对象。由于List的泛型参数在编译时被擦除,于是RestTemplate便无法确定List中的内容。「一般情况下」(REST接口返回值不是List类型)不会有问题,但是巧合的是,如果服务器端使用JSON对REST结果进行序列化,返回值会被封装在List中,此时,Spring已无法判断开发人员是想直接获得List封装的JSON内容还是需要更进一步使用Jackson库将JSON反序列化为Java对象。现实情况下,Spring选择的前者,于是便会抛出ClassCastException

上网搜了一圈,已经有人向Spring提交了enhancement请求(这里和这里,其中第一个链接中的walkaround可以work),但是目前没有milestone



-- EOF --
除非注明(如“转载”、“[zz]”等),本博文章皆为原创内容,转载时请注明: 「转载自程序员的信仰©」
本文链接地址:有关Java泛型的类型擦除(type erasing)

分享

  • 点击分享到 Facebook (在新窗口中打开) Facebook
  • 点击以分享到 X(在新窗口中打开) X
  • 更多
  • 点击分享到Reddit(在新窗口中打开) Reddit
  • 点击分享到Telegram(在新窗口中打开) Telegram
  • 点击以在 Mastodon 上共享(在新窗口中打开) Mastodon

赞过:

赞 正在加载……

相关

Today on history:

【2021】Elastic手撕AWS:「Amazon,我们完全不能接受 — 因此我们必须变更 Elastic 许可协议」
【2016】上海口音的普通话是一种什么样的体验? [zz]
【2009】才知道mac/linux下的MSN群怎么显示其他用户名
【2007】胡说胡有理 [花儿]
Posted in: 技术生活 Tagged: generics, java, rest, spring
← 解决Velocity+Spring的中文乱码问题
开发,架构,CTO →

android (9) apple (20) augmentum (9) Beijing (21) bt (8) career (28) coding (38) firefox (10) google (36) hibernate (11) ibm (11) iphone (10) java (93) linux (16) m$ (26) mac (58) macos (27) nazca (9) olympics (8) oo (8) playstation (10) rip (8) Shanghai (39) spring (9) tips (45) tommy emmanuel (8) ubuntu (12) usa (23) windows (9) 北航 (17) 博客 (29) 吐槽 (8) 周末 (9) 和谐社会 (26) 小资 (11) 愤青 (40) 方言 (10) 朋友 (77) 歌词 (8) 烟酒不分家 (18) 爱国 (19) 爱情 (8) 犯二 (15) 破解 (8) 足球 (11)

烫手山芋

  • 再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~ - 被踩了 27,412 脚
  • 生活,就是一个期待跟着一个期待 - 被踩了 21,358 脚
  • 星巴克饮品缩写大全(Starbucks Drink ID Codes)[zz] - 被踩了 18,415 脚
  • 从一个全角冒号说一下我为什么不感冒iOS - 被踩了 14,332 脚
  • 有关Character.isLetter()和Character.isLetterOrDigit() - 被踩了 13,591 脚

刚拍的砖

  • leo 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 花 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 无名氏 发表在《从一个全角冒号说一下我为什么不感冒iOS》
  • Jay 发表在《Mac OS geek级问题》
  • Wei Wang 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》

随便看看

  • 顽主——北京土话追溯之二 [zz]9 年 ago
  • 胡说胡有理 [花儿]19 年 ago
  • java.net论坛被黑(有图有真相)9 年 ago
  • 春晚,谁要这样的面子工程? [zz]19 年 ago
  • 误区!double类型做加减法不会有误差?6 年 ago

文以类聚

光阴似箭

其他操作

  • 登录
  • 条目 feed
  • 评论 feed
  • WordPress.org

Copyright © 2025 程序员的信仰.

Jay's Omega WordPress Theme by Jay

 

正在加载评论...
 

    %d