首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
华为云
V2EX  ›  Java

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

  •  
  •   abcbuzhiming · 293 天前 · 1238 次点击
    这是一个创建于 293 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 写法都应该指定容器里的类型的。

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

    12 回复  |  直到 2018-01-03 20:55:43 +08:00
        1
    lhx2008   293 天前
    这个应该是泛型的类型擦除导致的吧,Class 是没有泛型的,HashSet<String>的 Class 是 HashSet 不是 HashSet<String>
        2
    abcbuzhiming   293 天前
    @lhx2008 我知道 java 这玩意存在泛型擦除问题,但是奇怪的是,第二种写法也不对,第三种对了吧,但是 IDE 会报警说你没给容器指定元素的类型,感觉也不正统,所以我想知道这里正统的想法到底是啥
        3
    lhx2008   293 天前
    @abcbuzhiming
    IDE 报警用 @SuppressWarnings("unchecked")抑制就好,或者把 Class<T>的<T>去掉
    因为 HashSet<String>.class 的写法是语法错误的,所以只能写 HashSet.class,Class 是 HashSet
    然后,
    T 就是 HashSet,不是 HashSet<String>了,所以要 Abc<HashSet>
        4
    zhx1991   293 天前
    感觉你需要的是 ? 而不是 T
        5
    abcbuzhiming   293 天前
    @lhx2008 那为什么第二写法是错的呢?
    Abc<HashSet<String>> Abc = new Abc<HashSet<String>>(HashSet.class);
        6
    icegreen   293 天前
    如果你更关心容器内部的类型, 就把 String 当做参数传进去吧. 或者传 HashSet 和 String 两个参数?

    不了解业务场景, 无法给出准确建议~~.
        7
    abcbuzhiming   293 天前
    @icegreen 你没弄懂我的意思,这无关业务场景,而是 java 的泛型参数到底该如何使用的问题,如果我传入的是一个容器类型该如何使用,java 本身都是推荐在使用容器类型是指明容器元素类型的,但是这里明显有矛盾
        8
    finull   293 天前
    只用过 C# 的泛型,不理解这个类名称定义中已经有`T`了,为什么还要在构造函数中再穿个`Class<T>`进去
        9
    iEverX   293 天前
    @abcbuzhiming 因为 HashSet<String> 和 HashSet 的类型不一样啊
        10
    iEverX   293 天前
    类似的需求,可以用 TypeReference
        11
    zjp   292 天前
    @finull Java 泛型的实现里用了类型擦除,想要在运行时知道泛型的类型就得自己保存
        12
    SoloCompany   292 天前
    因为类型擦除, 所有 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) 有一定意义, 后者基本上毫无意义
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   953 人在线   最高记录 3762   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 17ms · UTC 17:41 · PVG 01:41 · LAX 10:41 · JFK 13:41
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1