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>
public static <T> T get(Class<T> clazz)
少写了返回值(。^▽^)
实现的效果类似于 C# Type.MakeGenericType
问题解决了哈(。^▽^)
用了下面两个方法
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>
)
1
Raymon111111 2020-01-07 22:35:57 +08:00
直接 get 的时候传 A.class 行吗?
|
2
yuxianjiazu OP @Raymon111111 不行的哦,需要返回 A<T>。
|
3
lhx2008 2020-01-07 22:39:10 +08:00
不能实现 1 的效果,A<t> 的话,用父类的泛型或者通配符泛型
|
4
winterbells 2020-01-07 22:40:04 +08:00
我记得 Java 的泛型是编译时的,跑起来后就没 <T> 这个东西了
kotlin 里有运行时的泛型,reified |
5
yuxianjiazu OP ```
public static <T> T get(Class<T> clazz) ``` 少写了返回值(。^▽^) |
6
Raymon111111 2020-01-07 22:43:15 +08:00
@yuxianjiazu get 完之后强转 A<T>
|
7
des 2020-01-07 22:44:50 +08:00 via Android
|
8
yuxianjiazu OP @Raymon111111 这样肯定不行的。。。返回的值是根据传入的 Class 进行运算的
|
9
mxalbert1996 2020-01-07 23:12:23 +08:00 via Android
关键词 type erasure。
@winterbells Kotlin 的 reified 一样是编译时的,想想为什么它只支持 inline fun。 |
10
yuxianjiazu OP @mxalbert1996
@des @winterbells @lhx2008 @Raymon111111 谢谢,了解了,还以为可以跟 C#一样。我还是把 D1, D2, ... Dn 写出来吧(;´д`)ゞ |
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) |
12
guyeu 2020-01-08 00:09:47 +08:00
把参数的类型从 Class 改成 ParamizedType 即可。
|
13
yuxianjiazu OP @guyeu 是 ParameterizedType 吗,我看看哈。
|
14
guyeu 2020-01-08 12:38:35 +08:00
@yuxianjiazu #13 啊是的,我拼错了。。。
|
15
Aresxue 2020-01-08 13:34:21 +08:00
泛型擦除,编译器不保留泛型信息,只能自己强转
|
16
okhowang 2020-01-08 14:19:07 +08:00
可以参考 jackson 的泛型逻辑,传进去一个匿名泛型类
mapper.readValue(jsonString, new TypeReference<Data<String>>() {}); |
17
SoloCompany 2020-01-08 18:15:30 +08:00 via iPhone
@okhowang 你这里的 data 和 string 都是编译期存在运行时没有的
|
18
yhvictor 2020-01-08 18:37:29 +08:00 via iPad
可以用 guava 的 typetoken
|
19
yuxianjiazu OP Java 的 ParameterizedTypeImpl.make 类似于 C#的 Type.MakeGenericType
|
20
codingbody 179 天前
@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 的实现方式。 |