1
hongch 2018-10-18 16:45:28 +08:00
没有用过 jackson,不出意外你传入一个 List<T>或者一个 T.class 最后都会解析成一个 type,可以看看他的源码最终需要的是什么直接传进去就好了
|
2
abcbuzhiming OP @hongch 要是这么容易我就不会提出来说了,核心问题是 Java 的泛型为什么没法处理容器内带有类型限定的这种情况
|
3
blindpirate 2018-10-18 16:55:42 +08:00 6
因为不存在 List<ClassName>.class,只有 List.class。至于为什么,需要从历史上讲起: https://www.zhihu.com/question/28665443
|
4
BBCCBB 2018-10-18 17:02:44 +08:00
这个类还有一个用 JavaType 作参数的构造函数, 用这个
|
5
yidinghe 2018-10-18 17:03:40 +08:00
容器泛型在运行时是被抹掉的,所以对于一个 List 对象,你在运行时并不能获取它针对哪种泛型。
|
6
gam2046 2018-10-18 17:04:29 +08:00
Java 的泛型是基于类型擦除 + 强制类型转换实现的。因此泛型的实际类型,在运行时期已经被抹掉了。无法返回其 Class。因此不允许这样的语法,没有人知道泛型的实际类型。
|
7
BBCCBB 2018-10-18 17:04:37 +08:00
TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, MyBean.class);
可能是因为你对 jackson 不熟. |
8
abcbuzhiming OP |
9
xingda920813 2018-10-18 17:22:34 +08:00
@abcbuzhiming 抛开本例中的 Jackson 不谈 (因为有其他的 API, 如上 @BBCCBB 回答的), 只论纯 Java 的话.
可以这样用: Jackson2JsonRedisSerializer<List<SomeClass>> serializer = (Jackson2JsonRedisSerializer<List<SomeClass>>) new Jackson2JsonRedisSerializer<>((Class<?>) List.class); 这样生成的 serializer 仍然是泛型化的. |
10
gaius 2018-10-18 17:41:05 +08:00
new TypeRefernece<List<SomeClass>>(){}
|
11
choice4 2018-10-18 17:48:22 +08:00
运行时泛型是 Object
|
12
abcbuzhiming OP @xingda920813 朋友,我楼顶补充说明一下,你这个方法也是没效的,仅仅不报错了,而且很奇葩的是,转换得到的其实是 List<LinkHashMap>类型,这个类型赋值给 List<ClassName>的时候,系统是不报错的,但是,如果你从最后的 List<ClassName>中取出一个对象,执行这个对象的方法的时候,就报错了,告诉你类型转换不能
|
13
gam2046 2018-10-18 18:14:58 +08:00
@abcbuzhiming 类型擦除后,基于多态,就是 Object。所以真正的类型就没了。
|
14
lovedebug 2018-10-18 18:17:23 +08:00 via Android
因为类型擦除发生在编译阶段,导致所有 list<t >都变成了 list,对应 class 都是 list.class。
|
15
TommyLemon 2018-10-18 18:27:09 +08:00
Gson 也差不多:
```java List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>(){}.getType()); ``` FastJSON 很方便: ```java List<Person> people = JSON.parseArray(jsonData, Person.class); ``` 不支持 Class<Type>.class 就是因为 Java 为了兼容 1.4 及以下的 JVM, 实现时用的是 泛型擦除 方式,只能在运行前静态检查类型, 编译通过后 Type 就换成 Object 了,只能强转获取。 这个你看下 ArrayList 的源码就知道了, 里面是用 Object[] elementData 来存列表数据的, get(int position) 内 return 的时候强转: ```java public E get(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); return (E) elementData[index]; } ``` |
16
MetoYou 2018-10-18 19:35:59 +08:00
最近也遇到了这个问题,绕不过去的,java 机制的问题。
|
17
Cbdy 2018-10-18 19:40:58 +08:00 via Android
Type reference 了解一下
Parameterized type 了解一下 |
18
beginor 2018-10-18 20:42:07 +08:00 via Android
因为 Java 的泛型是假的
|
19
micean 2018-10-18 20:56:48 +08:00
可以从字节码的层面去看
|
20
aristotll 2018-10-18 21:29:27 +08:00
effective java 有讲
|
21
ddup 2018-10-18 21:34:56 +08:00
没办法,因为运行时里没有泛型,缺少必要的类型信息,只能如此。
反正既然是 Java 就不要介意美丑的问题。 |
22
leeg810312 2018-10-18 23:37:06 +08:00 via Android
Java 早期设计偷懒埋下的巨坑,一味要求兼容性,以致于无法做到运行时的泛型支持,没有办法反射获取泛型类型信息,一直到现在 Java11 了还是没有解决,哪有永久的兼容性啊?
|
23
deming 2018-10-19 09:58:29 +08:00 1
可以用这个方法:
class CustomerInfoList extends List<CustomerInfoDto> {}; 然后就可以使用: Jackson2JsonRedisSerializer<CustomerInfoList> serializer = ... 来实现。 |
24
q397064399 2018-10-19 10:18:30 +08:00
List<List<List<List>>>> 在 Java 看来就是 List<Object> 就对了 :doge 这个算是历史遗留了
|
25
vincenteof 2018-10-19 10:57:17 +08:00
运行时和编译期的区别啊,编译后并没有你写的那个东西
|
26
xuanbg 2018-10-20 18:33:14 +08:00
3 楼正解
|