java - 类型推断在 java 中究竟是如何工作的?
问题描述
我正在尝试创建如下方法:
public <T> T getInstance(String key) {
Type type = new TypeToken<T>(){}.getType();
return deserialize(key, type); }
至于我不是(T)
在return
声明中强制转换,我希望编译器从外部上下文或至少从像这里这样的类型见证推断类型:
Integer i = container.<Integer>getInstance(mKey);
但在某些情况下,从未提及的getInstance()
方法返回Double
(更准确地说,序列化和反序列化使用谷歌的Gson库,初始对象是 的实例Integer
)。因此,我得到ClassCastException
.
那么在这种情况下类型推断究竟是如何工作的,为什么类型见证不起作用呢?是否可以在不指定Class<T>.class
为参数的情况下从外部上下文推断类型?
阐述:
经过一番研究,这个常见问题解答帮助我更好地理解了这个话题。
解决方案
您在这里遇到的一般问题是没有任何东西可以限制输出与输入相关。
所以,这是有效的:
Integer i = container.<Integer>getInstance(mKey); // I doubt you even need the <Integer>
但这也是有效的:
String s = container.<String>getInstance(mKey);
该getInstance
方法所看到的只是: 它对ormKey
的任何内容一无所知。所以这在两种情况下都必须返回相同的结果——但至少其中一个是错误的(或者它们都在返回)。<Integer>
<String>
null
因为getInstance
只接收 的值mKey
,所以类型标记在两种情况下都是相同的。您可以通过实现自己的类型令牌类来看到这一点:
abstract static class TypeToken<T> {
Type getType() {
return getClass().getGenericSuperclass();
}
}
static <T> TypeToken<T> getTypeToken() {
return new TypeToken<T>() {};
}
public static void main (String[] args) throws java.lang.Exception
{
TypeToken<String> stringTypeToken = getTypeToken();
TypeToken<Integer> integerTypeToken = getTypeToken();
System.out.println(stringTypeToken.getType());
System.out.println(integerTypeToken.getType());
System.out.println(stringTypeToken.getType().equals(integerTypeToken.getType()));
}
输出:
Ideone$TypeToken<T>
Ideone$TypeToken<T>
true
在您的代码中,Type type = new TypeToken<T>(){}.getType();
没有获取TypeToken
呼叫站点类型,它只是获取T
. 所以你没有得到一个TypeToken<Integer>
.
从编译的意义上说,这是有效的,但在它没有做你想让它做的事情的意义上,它不起作用。
正确执行此操作的方法是将 注入TypeToken<T>
作为方法参数。在呼叫站点上变得非常麻烦;但这就是您使用具有已擦除类型的语言所付出的代价。
推荐阅读
- reactjs - 在 React 中使用单个 onChange 处理程序处理多个输入
- java - 如何打开 Play 商店以显示给定其自定义 url 方案的应用程序?
- javascript - 你可以使用 Nodejs 的 Create-React-App npm start 吗?
- android - 提供捆绑包和 APK 时如何删除 APK
- pytorch - CUDA 错误 59:触发了设备端断言
- python - 用于模板匹配的 Python OpenCV
- python - PRAW:你是怎么得到你的提交链接的?
- c# - 您如何通过共同属性将两个自定义对象相互比较?
- php - 延迟睡眠时遇到问题
- nativescript - 获取 ios [Nativescript] 的新构建错误