转:有关Java泛型的类型擦除(type erasing)
转载自:拈花微笑
自从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方法:
| Java | | copy code | | ? |
| 1 | |
| 2 |
@RequestMapping(value = "...", method = RequestMethod.GET) |
| 3 |
@ResponseBody |
| 4 |
public List<DomainClass> doSomethingREST() {
|
| 5 |
List<DomainClass> domainObjs = ... ; |
| 6 |
return domainObjs; |
| 7 |
} |
| 8 |
在运行时,Spring MVC会将List转换成JSON字符串并返回至客户端。但是如果我在另一个service中使用RestTemplate直接调用该REST接口,问题便来了:
| Java | | copy code | | ? |
| 1 | |
| 2 |
List<DomainClass> domainObjs = this.restTemplate.getForObject(this.restURL, List.class); |
| 3 |
关键在于第二个参数,是返回值的类型,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 –
转:有关Java泛型的类型擦除(type erasing)的更多相关文章
- Java泛型:类型擦除
类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...
- Java泛型之类型擦除
类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...
- java 泛型的类型擦除与桥方法
泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...
- java 泛型的类型擦除和桥方法
oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...
- Java泛型-类型擦除
一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...
- JAVA 泛型之类型擦除
★ 泛型是 JDK 1.5 版本引进的概念,之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容. CollectionTest.java ---编译成CollectionTest. ...
- Java泛型的类型擦除
package com.srie.testjava; import java.util.ArrayList; import java.util.List; public class TestGener ...
- Java泛型类与类型擦除
转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...
- java之集合类框架的简要知识点:泛型的类型擦除
这里想说一下在集合框架前需要理解的小知识点,也是个人的肤浅理解,不知道理解的正不正确,请大家多多指教.这里必须谈一下java的泛型,因为它们联系紧密,我们先看一下这几行代码: Class c1 = n ...
随机推荐
- java之JDBC
java之JDBC 一.什么是JDBC Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提 ...
- .net邮件发送实例 邮件内容为网页模板
.net邮件发送实例 邮件内容为网页模板 2009-07-03 09:31:01| 分类: .NET|字号 订阅 Encoding encoding = Encoding.GetEncod ...
- JS遍历对象或者数组
一.纯js实现 <script> var obj = {"player_id":"GS001","event_id":" ...
- Access数据库数据转换Table.Json
使用WPF组件 xaml <Window x:Class="JsonConvert.MainWindow" xmlns="http://schemas.micros ...
- ViewPager 嵌套Listview 让Listview响应 ViewPager 左右滑事件
一段拦截判断而已. 之前一直误解了一个拦截的描述.导致搞了半天. 结论: onInterceptTouchEvent 返回true,就由本身View的onTouchEvent进行事件消费. /** ...
- hibernate的get、load的方法的区别,IllegalArgument异常
关于hibernate中的load,get,以及延迟加载问题 今天在使用hibernate时,发现一异常: could not initialize proxy - no Session 查询资料之后 ...
- Python的多线程实现
概述 Python虚拟机使用GIL(Global Interpreter Lock,全局解释器锁)来实现互斥线程对共享资源的访问,暂时无法利用多处理器的优势. Python中,thread和threa ...
- python -i filename
今天学习的时候看见python -i filaname 这个命令,书上说使用这个命令可以去执行filename文件中的代码.但是今天在使用的时候却一直报错,经过多次测试才把问题解决. 原来这个命令是不 ...
- ARM内核和架构都是什么意思,它们到底是什么关系?
ARM产品越来越丰富,命名也越来越多.很多朋友提问: ARM内核和架构都是什么意思?内核和架构的关系是什么?比如ARMv7架构,这个架构指的是什么?小编选出了几个精彩回答!希望对嵌友们在选择设计电路时 ...
- 一个测ip和端口是否联通的工具类
public class TestIp { public static void main(String[] args) { Socket connect = new Socket(); try { ...