我目前正在尝试重构项目,以避免不得不使用番石榴作为依赖项。 我主要将其用于反射相关的功能,但是在大多数情况下,我可以找到一种替代方法。
但是,我目前无法解决一种情况: 我尝试检索当前类的通用参数的类。
使用Guava
可以正常工作,因为TokenType
返回的Type可以强制转换为Class。
番石榴:
(Class<I>) new com.google.common.reflect.TypeToken<I>(getClass()) {}.getType();
我尝试使用TypeToken
中的Gson
代替此调用,但是显然有关我的信息丢失了,并且此调用的结果是TypeVariable
,而不是保留为执行后的类:
Gson:
(Class<I>) new com.google.gson.reflect.TypeToken<I>() {}.getType();
据我所知,getClass()参数是为什么不保留上下文的线索。
当我使用具有相同签名的Guava
时:
(Class<I>) new com.google.gson.reflect.TypeToken<I>() {}.getType();
我收到此错误消息:
java.lang.IllegalStateException:无法为类型变量构造TypeToken。 您可能打算调用可以为您解析类型变量的新TypeToken(getClass())。 如果确实需要创建类型变量的TypeToken,请改用TypeToken.of()。
我也将Gson
视为(受软件包保护的)构造函数,并使用Type
作为参数。
有没有办法仅使用Gson
获取通用参数的类?
更好地理解这个问题,我可以说区别似乎在于这两个方法返回的基础Type实现中。
番石榴可以投给Class<I>
,而格森人则不能。我不确定Guava的基础实现是什么,但是Gson使用了TypeVariable
。
目前,我发现的解决方法是通过将Gson TypeToken(类型)的结果与使用当前类作为上下文的此方法合并来利用Guava使用的两种信息(类型+当前类):
public static Type getActualType(Class context, Type parameterizedType) {
if (parameterizedType instanceof TypeVariableImpl) {
TypeVariable[] genericParameters = context.getSuperclass().getTypeParameters();
Type[] implementations = ((ParameterizedTypeImpl) context.getGenericSuperclass()).getActualTypeArguments();
for (int i = 0; i < genericParameters.length; i++) {
if (genericParameters[i].getName().equals(((TypeVariableImpl) parameterizedType).getName())) {
return implementations[i];
}
}
}
return parameterizedType;
}
(此实现来自buremba/netty-rest project)
这使我可以通过调用以下方法检索所需的类:
(Class<I>) getActualType(getClass(), new com.google.gson.reflect.TypeToken<I>() {}.getType());
这似乎有些费力,但我不确定这是否是最好的方法。
注意:该问题也被提出为a Github issue on the Gson Project