获取泛型 Class 问题

2020 年 1 月 7 日
 yuxianjiazu
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>

4887 次点击
所在节点    Java
20 条回复
Raymon111111
2020 年 1 月 7 日
直接 get 的时候传 A.class 行吗?
yuxianjiazu
2020 年 1 月 7 日
@Raymon111111 不行的哦,需要返回 A<T>。
lhx2008
2020 年 1 月 7 日
不能实现 1 的效果,A<t> 的话,用父类的泛型或者通配符泛型
300
2020 年 1 月 7 日
我记得 Java 的泛型是编译时的,跑起来后就没 <T> 这个东西了
kotlin 里有运行时的泛型,reified
yuxianjiazu
2020 年 1 月 7 日
```
public static <T> T get(Class<T> clazz)
```
少写了返回值(。^▽^)
Raymon111111
2020 年 1 月 7 日
@yuxianjiazu get 完之后强转 A<T>
des
2020 年 1 月 7 日
@winterbells
确实 java 的泛型是编译时的,拿出来的是 object
C#是运行时的
yuxianjiazu
2020 年 1 月 7 日
@Raymon111111 这样肯定不行的。。。返回的值是根据传入的 Class 进行运算的
mxalbert1996
2020 年 1 月 7 日
关键词 type erasure。
@winterbells Kotlin 的 reified 一样是编译时的,想想为什么它只支持 inline fun。
yuxianjiazu
2020 年 1 月 7 日
@mxalbert1996
@des
@winterbells
@lhx2008
@Raymon111111

谢谢,了解了,还以为可以跟 C#一样。我还是把 D1, D2, ... Dn 写出来吧(;´д`)ゞ
SoloCompany
2020 年 1 月 7 日
可以改一下方法签名

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

get(A.class, String.class)
guyeu
2020 年 1 月 8 日
把参数的类型从 Class 改成 ParamizedType 即可。
yuxianjiazu
2020 年 1 月 8 日
@guyeu 是 ParameterizedType 吗,我看看哈。
guyeu
2020 年 1 月 8 日
@yuxianjiazu #13 啊是的,我拼错了。。。
Aresxue
2020 年 1 月 8 日
泛型擦除,编译器不保留泛型信息,只能自己强转
okhowang
2020 年 1 月 8 日
可以参考 jackson 的泛型逻辑,传进去一个匿名泛型类
mapper.readValue(jsonString, new TypeReference<Data<String>>() {});
SoloCompany
2020 年 1 月 8 日
@okhowang 你这里的 data 和 string 都是编译期存在运行时没有的
yhvictor
2020 年 1 月 8 日
可以用 guava 的 typetoken
yuxianjiazu
2020 年 1 月 8 日
Java 的 ParameterizedTypeImpl.make 类似于 C#的 Type.MakeGenericType
Reminders
2024 年 6 月 26 日
@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 的实现方式。

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

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

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

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

© 2021 V2EX