请教一下关于 Java 泛型的问题。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Renco
V2EX    Java

请教一下关于 Java 泛型的问题。

  •  
  •   Renco 303 天前 3719 次点击
    这是一个创建于 303 天前的主题,其中的信息可能已经有所发展或是发生改变。
    24 条回复    2024-12-12 09:09:23 +08:00
    Renco
        1
    Renco  
    OP
       303 天前
    Renco
        2
    Renco  
    OP
       303 天前
    Renco
        3
    Renco  
    OP
       303 天前
    为啥这样写,返回的值默认是 Object ,而不是参数中的 EqpProdInfo 类。
    Renco
        4
    Renco  
    OP
       303 天前
    泛型平时用的比较少,这次写新功能的时候,尝试用用,遇上了这个错。
    tars13344
        5
    tars13344  
       303 天前
    看你 getKey 方法的 tclass 参数也没有用到,如果只是想用来指定返回值类型的话 是不需要这个参数的,在调用的时候直接 cache.<EqpProdInfo>getIfPresent() 就可以了
    tars13344
        6
    tars13344  
       303 天前
    @tars13344 #5 额 最后一句有符号被 md 语法吃掉了
    ```java
    cacheHelper.<EqpProdInfo>geBykey()
    ```
    tars13344
        7
    tars13344  
       303 天前
    @tars13344 #5 ...这个符号是打不出来了,总之就是在调用函数的时候 在函数名和. 之间用尖括号包围指定 T 的类型即可
    Renco
        8
    Renco  
    OP
       303 天前
    @tars13344 #7 谢谢,忘记了泛型可以这样写,不过这个依旧会报错,返回类型一直是 Object
    w11ya
        9
    w11ya  
       303 天前
    泛型擦除
    ftsland
        10
    ftsland  
       303 天前
    你是想 Cache 里面 Value 可以保存任意类型吗?

    ![这是图片 1]( https://meee.com.tw/R8cfkNx "这是图片 1")
    ![这是图片 2]( https://meee.com.tw/KLKSVhy "这是图片 2")
    ftsland
        11
    ftsland  
       303 天前
    MD 不知道为啥发不出来, 如果需要 Cache 里面是任意类型, 不要使用 CacheHelper<K, V> , 使用 CacheHelper<K> , Cache 用 Cache<K,Object> getByKey 去掉 class 参数,
    Renco
        12
    Renco  
    OP
       303 天前
    @ftsland #11 好,我试试,谢谢!
    bli22ard
        13
    bli22ard  
       303 天前
    建议
    public <T extends V> T get(String cacheKey,K key){
    Cache<K,V> cache=cacheMap.get(cacheKey);
    if(cache!=null){
    return (T) cache.get(key);
    }
    return null;
    }

    你是要限定 V 的类型范围,因为你已经限定了 cache 的 value 是个 V 类型。传 Class<T> clazz , 那你的 V 类型还不如直接定义为 Object 。另外你的成员变量 cacheMap 会有并发安全问题,当然如果 CacheHelper 不会有并发问题,那可以忽略并发安全问题
    xiangbohua
        14
    xiangbohua  
       303 天前
    好像不是因为范形擦除的原因,我觉得还是因为类上面定义的类型是 V ,但是方法上传的是 T ,T 和 V 之间又没有范性约束那么直接理解为两个不相关的类就好了。既然不相关,那编译器只能认为返回的是 object (拿不到任何类型限定信息)。
    如果有错误可指出
    ajieggoto318
        15
    ajieggoto318  
       302 天前
    如果 T 是 V 的父类可以把 getByKey 方法的<T>改为<T super V>,然后代码好像没有问题,重启一下 idea ,看看是不是 idea 抽风了
    jaredyam
        16
    jaredyam  
       302 天前
    看起来是 IDEA 缓存的问题
    yazinnnn0
        17
    yazinnnn0  
       302 天前


    调用方法的时候标一下范型的具体类型, java 的语法比较弱鸡, 没办法根据返回值的接收类型来推断范型的类型, 也没办法像 kotlin 的 inline+refied 那样获取范型的具体类型

    kotlin 的范型和类型推断好很多, 所以有人(我)说 kotlin 是 java 和 ocaml 的结合体, 现代语言的牛逼的类型推断能力都是从 ml 系语言里借鉴来的(点草 rust 批)
    635925926
        18
    635925926  
       302 天前
    把 T 换成 V
    ychost
        19
    ychost  
       302 天前
    应该是 IDEA 的问题,清空缓存重试下,
    dragondove
        20
    dragondove  
       302 天前
    @yazinnnn0 根据返回类型实际上是放弃类型安全,不过可以通过其他方式补全(比如楼主用的 Class<T>的方式,但是 Class<T> 存在 T 不能有泛型的限制,都是历史债,建议是自己定义一个 TypeInfo 之类的类型来使用),下面的例子是 java 中根据返回类型推断泛型的例子,java 在这方面不存在你说的问题。

    ```java
    public class Main {
    static Object o = new Object();
    @SuppressWarnings("unchecked")
    static <T> T get() {
    return (T) o;
    }
    public static void main(String[] args) {
    String x = get();
    }
    }
    ```
    entrance
        21
    entrance  
       302 天前
    cacheHelper 注入时没指定泛型类型,可以试下这样: cacheHelper<String, List<String>> cacheHelper
    AV1
        22
    AV1  
       302 天前
    @yazinnnn0
    是泛型,不是范型。generic 是通用、泛用之义。
    ChenFanlin
        23
    ChenFanlin  
       302 天前
    简单写了个小 demo 试了下,好像也没报错?
    ```
    public class Test {
    public static void main(String[] args) {
    Helper<String, Integer> helper = new Helper<>();
    Key key = helper.getByKey("", "", Key.class);
    System.out.println(key);
    }

    private static class Key {
    }

    private static class Helper<K, V> {
    public <T> T getByKey(String cacheKey, K key, Class<T> tClass) {
    return null;
    }
    }
    }
    ```
    levintrueno
        24
    levintrueno  
       302 天前
    看看你的 cacheHelper 注入的时候是怎么定义的,如果 key 都是 String ,那么可以 @Resource CacheHelper<String, ?> cacheHelper; 那个 vClass 参数也可以不用了,应该可以直接返回你定义的类型。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3968 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 04:10 PVG 12:10 LAX 21:10 JFK 00:10
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86