获取泛型 Class 问题

2020-01-07 22:16:07 +08:00
 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>

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

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

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

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