我正在尝试在我的 Java 代码中获取泛型类型
<T>
的类。我使用阿里巴巴的 FastJSON 进行 JSON 处理。以下是我的代码的关键部分:
来电者:
public Features findFeatureById(BigDecimal id) {
return mixedCacheService.get(FEATURE, id.toString(), new MixedCacheService.Func<>(() -> featuresDao.selectById(id)));
}
被叫者:
public <T> T get(@NotNull CacheBaseConstants cacheBaseConstants, @NotNull String key, @NotNull Supplier<T> getter) {
String value = get(cacheBaseConstants, key);
if ("".equals(value)) {
return null;
}
// How can I get T.class here?
return Optional.ofNullable(value)
.map(o -> JSON.parseObject(value, T.class))
.orElseGet(() -> put(cacheBaseConstants, key, getter));
}
我试图延长
com.alibaba.fastjson.TypeReference
:
public static class Func<T> extends TypeReference<T> {
private Supplier<T> supplier;
public Func(Supplier<T> supplier) {
super();
this.supplier = supplier;
}
public T get() {
return supplier.get();
}
}
我也尝试过使用
getter.supplier.getClass().getGenericSuperclass()
,但它返回了Object
。
我想知道如何成功获得
<T>
的课程。任何见解或建议将不胜感激!
你不能。这就是“擦除”的意思。泛型是编译器想象出来的。如果在编译时不可能知道,那就不可能知道。
泛型保留在签名中。换句话说,给定:
class Foo<K, T extends List<K>> {}
然后在运行时你仍然可以得到泛型,但是你能得到的是在编译时的东西。换句话说,你可以从字面上得到:
List<K>
这一事实。你无法得到的,已被给予,说:
Foo<String, ArrayList<String>> x = new Foo<>();
System.out.println(deriveStatsFrom(x));
deriveStatsFrom
在这里不可能获得String
或ArrayList<String>
。这不是“难”的问题,而是“难”的问题。不,这是一个“不可能”的问题 - 编译器会删除所有这些东西,因此在运行时根本不可能确定这一点。
你提到com.alibaba.fastjson.TypeReference
。
这个类是明确设计来解决这个问题的。 要使用它,您
必须像这样编写类型引用:
TypeReference<List<String>> stringListRef = new TypeReference<List<String>>() {};
注意最后奇怪的
{}
。
这是强制性的。这创建了一个很小的类,类 do 带有它们签名的泛型。换句话说,上面有很多语法糖:
class SomeIrrelevantName extends TypeReference<List<String>> {}
TypeReference<List<String>> stringListRef = new SomeIrrelevantName();
因此,
stringListRef.getClass()
让您能够实现它。
这就是 API 希望您做的事情。在您的方法中,您必须添加类型为TypeReference<T>
的参数;您粘贴的这个方法
无法知道,因此您无法解决它。你真的必须不断地告诉自己这一点:如果在编译时你不知道,那么你就不知道。无论在编译时知道什么,都必须制作这个东西并将其传递出去。