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 300 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 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 的实现方式。 |