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

获取泛型 Class 问题

  •  
  •   yuxianjiazu 2020-01-07 22:16:07 +08:00 4607 次点击
    这是一个创建于 2112 天前的主题,其中的信息可能已经有所发展或是发生改变。
    public class A<T> { } public class B { public static <T> get(Class<T> clazz) { //... } public static void main(String[] args) { System.out.println(get((A<String>).class)); // 1 错误写法 } } 

    请问,不添加

    class C extends A<String> { } 

    的情况下, 怎么实现 1 的效果(C#可以实现,Java 不知道怎么实现)

    使用场景:A<t>里面的 T 可以是(D1, D2, ... Dn),不想分别多写一个(C1, C2, ... Cn)类
    A<(D1, D2, ... Dn)> 的 Class 是 B.get 的参数</t>

    第 1 条附言    2020-01-07 22:59:30 +08:00
    public static <T> T get(Class<T> clazz) 

    少写了返回值(。^^)

    实现的效果类似于 C# Type.MakeGenericType

    第 2 条附言    2020-01-08 20:47:55 +08:00

    问题解决了哈(。^^)

    用了下面两个方法

    public class ParameterizedTypeImpl implements ParameterizedType { ParameterizedTypeImpl make(Class<?> var0, Type[] var1, Type var2) { return new ParameterizedTypeImpl(var0, var1, var2); } } 

    public class ClassHelper { public static Type getGenericClass(Class<?> clazz) { return clazz.getGenericSuperclass()).getActualTypeArguments()[0]; } } 

    Map<Class<?>, Object> kvs 改成 Map<Type, Object> kvs B.get的参数也改成Type

    (基本就是Class<T>参数改成了Type,然后用上面的代码获取Type:A<T>)

    20 条回复    2024-06-26 18:19:04 +08:00
    Raymon111111
        1
    Raymon111111  
       2020-01-07 22:35:57 +08:00
    直接 get 的时候传 A.class 行吗?
    yuxianjiazu
        2
    yuxianjiazu  
    OP
       2020-01-07 22:37:41 +08:00 via Android
    @Raymon111111 不行的哦,需要返回 A<T>。
    lhx2008
        3
    lhx2008  
       2020-01-07 22:39:10 +08:00
    不能实现 1 的效果,A<t> 的话,用父类的泛型或者通配符泛型
    300
        4
    300  
       2020-01-07 22:40:04 +08:00
    我记得 Java 的泛型是编译时的,跑起来后就没 <T> 这个东西了
    kotlin 里有运行时的泛型,reified
    yuxianjiazu
        5
    yuxianjiazu  
    OP
       2020-01-07 22:40:14 +08:00
    ```
    public static <T> T get(Class<T> clazz)
    ```
    少写了返回值(。^^)
    Raymon111111
        6
    Raymon111111  
       2020-01-07 22:43:15 +08:00
    @yuxianjiazu get 完之后强转 A<T>
    des
        7
    des  
       2020-01-07 22:44:50 +08:00 via Android
    @winterbells
    确实 java 的泛型是编译时的,拿出来的是 object
    C#是运行时的
    yuxianjiazu
        8
    yuxianjiazu  
    OP
       2020-01-07 22:45:07 +08:00
    @Raymon111111 这样肯定不行的。。。返回的值是根据传入的 Class 进行运算的
    mxalbert1996
        9
    mxalbert1996  
       2020-01-07 23:12:23 +08:00 via Android
    关键词 type erasure。
    @winterbells Kotlin 的 reified 一样是编译时的,想想为什么它只支持 inline fun。
    yuxianjiazu
        10
    yuxianjiazu  
    OP
       2020-01-07 23:26:59 +08:00
    @mxalbert1996
    @des
    @winterbells
    @lhx2008
    @Raymon111111

    谢谢,了解了,还以为可以跟 C#一样。我还是把 D1, D2, ... Dn 写出来吧(;д`)
    SoloCompany
        11
    SoloCompany  
       2020-01-07 23:52:06 +08:00 via iPad
    可以改一下方法签名

    public static <C, T> T get(Class<C> type, Class<T> genericType)

    get(A.class, String.class)
    guyeu
        12
    guyeu  
       2020-01-08 00:09:47 +08:00
    把参数的类型从 Class 改成 ParamizedType 即可。
    yuxianjiazu
        13
    yuxianjiazu  
    OP
       2020-01-08 01:16:57 +08:00 via Android
    @guyeu 是 ParameterizedType 吗,我看看哈。
    guyeu
        14
    guyeu  
       2020-01-08 12:38:35 +08:00
    @yuxianjiazu #13 啊是的,我拼错了。。。
    Aresxue
        15
    Aresxue  
       2020-01-08 13:34:21 +08:00
    泛型擦除,编译器不保留泛型信息,只能自己强转
    okhowang
        16
    okhowang  
       2020-01-08 14:19:07 +08:00
    可以参考 jackson 的泛型逻辑,传进去一个匿名泛型类
    mapper.readValue(jsonString, new TypeReference<Data<String>>() {});
    SoloCompany
        17
    SoloCompany  
       2020-01-08 18:15:30 +08:00 via iPhone
    @okhowang 你这里的 data 和 string 都是编译期存在运行时没有的
    yhvictor
        18
    yhvictor  
       2020-01-08 18:37:29 +08:00 via iPad
    可以用 guava 的 typetoken
    yuxianjiazu
        19
    yuxianjiazu  
    OP
       2020-01-08 20:50:51 +08:00
    Java 的 ParameterizedTypeImpl.make 类似于 C#的 Type.MakeGenericType
    codingbody
        20
    codingbody  
       2024-06-26 18:19:04 +08:00
    @yuxianjiazu
    public class A<T> {

    public static Type getGenericClass(Class<?> clazz) {
    return ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public static void main(String[] args) {
    A<List<String>> a = new A<>() {};
    System.out.println("Generic type: " + getGenericClass(a.getClass())); // 输出: Generic type: java.util.List<java.lang.String>
    }
    }

    这里必须用 new A<>() {} 这种匿名内部类的方式吧,这也就是 @okhowang 提到的 jackson 的实现方式。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 19:41 PVG 03:41 LAX 12:41 JFK 15:41
    Do have faith in what you're doing.
    ubao msn 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