[英]Unchecked assignment warning
我使用的是Android Studio 1.1.0。
这不会导致警告:
public static class A {
public Map<Integer, String> getMap() {
return null;
}
}
public static class B {
public void processA(A a) {
Map<Integer, String> map = a.getMap();
}
}
但是做A
通用的:
public static class A<T> {
public Map<Integer, String> getMap() {
return null;
}
}
这一行:
Map<Integer, String> map = a.getMap();
现在给你一个警告: "Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'
。
尽管getMap
的签名完全独立于T
,但代码对于Map
包含的类型是明确的。
我知道我可以通过重新实现processA
来消除警告,如下所示:
public <T> void processA(A<T> a) {
Map<Integer, String> map = a.getMap();
}
但为什么我必须这样做? 什么T
在这里至关重要?
所以,问题是 - 为什么类型擦除不仅影响T
(这是可以理解的 - 如果我传递的是A
的实例, T
是未知的),还有“硬编码”的通用签名,如<Integer, String>
在这种情况下?
在你的第二种情况下:
public void processA(A a)
A
是什么意思? 这是指A<String>
还是A<List<String>>
还是什么? 您可能没有使用与A
类型相关的任何内容,但是编译器不知道这个事实。 对于编译器,只是A
是恐慌的标志。
在您的情况下,因为您不需要特别知道A的类型,您可以:
public void processA(A<?> a) {
Map<Integer, String> map = a.getMap();
}
参数类型为A<?>
意味着,您没有特别关注A
的类型,只需指定一个外卡。 对你而言,它意味着:任何类型的A
作为其泛型类型的任何对象都可以。 实际上,这意味着你不知道这种类型。 它没用,因为你不能以类型安全的方式做任何与A
有关的事情?
可以是几乎任何东西!
但是根据你的方法体,在世界上使用A<?>
是完全有道理的,因为身体中你实际上不需要A
的类型
当你的意思是接受任何可能类型T
的A<T>
但不需要T
,可以通过使用通配符并写入A<?>
来正确表达。 这样做将消除代码中的警告:
public void processA(A<?> a) {
Map<Integer, String> map = a.getMap();
}
使用裸A
类型不会被等效地处理。 正如Java语言规范中所解释的那样,这样的原始类型不打算在新代码中使用:
未经检查的转换用于实现在引入泛型类型之前编写的遗留代码与已经过转换以使用泛型的库(我们称之为泛化的过程)的平滑互操作。 在这种情况下(最值得注意的是,java.util中的Collections Framework的客户端),遗留代码使用原始类型(例如Collection而不是Collection <String>)。 原始类型的表达式作为参数传递给库方法,这些库方法使用与其相应形式参数的类型相同类型的参数化版本。
在使用泛型的类型系统下,这样的调用不能显示为静态安全。 拒绝此类调用将使大量现有代码无效,并阻止它们使用较新版本的库。 反过来,这将阻止图书馆供应商利用通用性。 为了防止这种不受欢迎的事件转换,可以将原始类型转换为原始类型引用的泛型类型声明的任意调用。 虽然转换是不合理的,但它被视为对实用性的让步。 在这种情况下会发出未经检查的警告。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.