这样的泛型定义到底如何调用才是对的呢?

2018-01-02 21:05:28 +08:00
 abcbuzhiming
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 写法都应该指定容器里的类型的。

我查了不少资料,看起来最后一种才是对的,但是为啥最后一种那么别扭呢

2383 次点击
所在节点    Java
12 条回复
lhx2008
2018-01-02 21:16:43 +08:00
这个应该是泛型的类型擦除导致的吧,Class 是没有泛型的,HashSet<String>的 Class 是 HashSet 不是 HashSet<String>
abcbuzhiming
2018-01-02 21:26:34 +08:00
@lhx2008 我知道 java 这玩意存在泛型擦除问题,但是奇怪的是,第二种写法也不对,第三种对了吧,但是 IDE 会报警说你没给容器指定元素的类型,感觉也不正统,所以我想知道这里正统的想法到底是啥
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>
zhx1991
2018-01-02 22:15:12 +08:00
感觉你需要的是 ? 而不是 T
abcbuzhiming
2018-01-02 22:21:25 +08:00
@lhx2008 那为什么第二写法是错的呢?
Abc<HashSet<String>> Abc = new Abc<HashSet<String>>(HashSet.class);
icegreen
2018-01-02 22:24:19 +08:00
如果你更关心容器内部的类型, 就把 String 当做参数传进去吧. 或者传 HashSet 和 String 两个参数?

不了解业务场景, 无法给出准确建议~~.
abcbuzhiming
2018-01-02 22:31:17 +08:00
@icegreen 你没弄懂我的意思,这无关业务场景,而是 java 的泛型参数到底该如何使用的问题,如果我传入的是一个容器类型该如何使用,java 本身都是推荐在使用容器类型是指明容器元素类型的,但是这里明显有矛盾
finull
2018-01-02 23:03:55 +08:00
只用过 C# 的泛型,不理解这个类名称定义中已经有`T`了,为什么还要在构造函数中再穿个`Class<T>`进去
iEverX
2018-01-02 23:12:26 +08:00
@abcbuzhiming 因为 HashSet<String> 和 HashSet 的类型不一样啊
iEverX
2018-01-02 23:13:21 +08:00
类似的需求,可以用 TypeReference
zjp
2018-01-03 10:50:29 +08:00
@finull Java 泛型的实现里用了类型擦除,想要在运行时知道泛型的类型就得自己保存
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) 有一定意义, 后者基本上毫无意义

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/419503

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX