public class Abc<T>{
private final JavaType javaType;
public Abc(Class<T> type) {
this.javaType = getJavaType(type);
}
}
我调用的时候
Abc<HashSet<String>> Abc = new Abc<HashSet<String>>(HashSet<String>.class);
通不过,报错
Abc<HashSet<String>> Abc = new Abc<HashSet<String>>(HashSet.class);
还是报错
Abc<HashSet> Abc = new Abc<HashSet>(HashSet.class);
这样终于可以了,但是没有指定 HashSet 容器内部的类型,IDE 报警,而且我也觉得这好像不是正统的 java 写法,正统的 java 写法都应该指定容器里的类型的。
我查了不少资料,看起来最后一种才是对的,但是为啥最后一种那么别扭呢
1
lhx2008 2018-01-02 21:16:43 +08:00
这个应该是泛型的类型擦除导致的吧,Class 是没有泛型的,HashSet<String>的 Class 是 HashSet 不是 HashSet<String>
|
2
abcbuzhiming OP @lhx2008 我知道 java 这玩意存在泛型擦除问题,但是奇怪的是,第二种写法也不对,第三种对了吧,但是 IDE 会报警说你没给容器指定元素的类型,感觉也不正统,所以我想知道这里正统的想法到底是啥
|
3
lhx2008 2018-01-02 21:50:21 +08:00
@abcbuzhiming
IDE 报警用 @SuppressWarnings("unchecked")抑制就好,或者把 Class<T>的<T>去掉 因为 HashSet<String>.class 的写法是语法错误的,所以只能写 HashSet.class,Class 是 HashSet 然后, T 就是 HashSet,不是 HashSet<String>了,所以要 Abc<HashSet> |
4
zhx1991 2018-01-02 22:15:12 +08:00
感觉你需要的是 ? 而不是 T
|
5
abcbuzhiming OP @lhx2008 那为什么第二写法是错的呢?
Abc<HashSet<String>> Abc = new Abc<HashSet<String>>(HashSet.class); |
6
icegreen 2018-01-02 22:24:19 +08:00
如果你更关心容器内部的类型, 就把 String 当做参数传进去吧. 或者传 HashSet 和 String 两个参数?
不了解业务场景, 无法给出准确建议~~. |
7
abcbuzhiming OP @icegreen 你没弄懂我的意思,这无关业务场景,而是 java 的泛型参数到底该如何使用的问题,如果我传入的是一个容器类型该如何使用,java 本身都是推荐在使用容器类型是指明容器元素类型的,但是这里明显有矛盾
|
8
finull 2018-01-02 23:03:55 +08:00
只用过 C# 的泛型,不理解这个类名称定义中已经有`T`了,为什么还要在构造函数中再穿个`Class<T>`进去
|
9
iEverX 2018-01-02 23:12:26 +08:00
@abcbuzhiming 因为 HashSet<String> 和 HashSet 的类型不一样啊
|
10
iEverX 2018-01-02 23:13:21 +08:00
类似的需求,可以用 TypeReference
|
12
SoloCompany 2018-01-03 20:55:43 +08:00
因为类型擦除, 所有 concret type 的 Class<T> 中的 T 只能是 raw type
数组也有类似的限制: new T[] 中的 T 也只能是 raw type 如果你需要 parameterized type 的 class object 或数组, 只能靠 upcast 比如 List<String>[] list = new List[]; // new List<String>[] 是非法的 Class<List<String>> classOfListOfString = List.class; // List<String>.class 当然也是非法的 前者 (parameterized array) 有一定意义, 后者基本上毫无意义 |