Java 未检查分配警告
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28808053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unchecked assignment warning
提问by Konrad Morawski
I am using Android Studio 1.1.0.
我正在使用 Android Studio 1.1.0。
This causes no warning:
这不会导致警告:
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();
}
}
But make A
generic:
但要A
通用:
public static class A<T> {
public Map<Integer, String> getMap() {
return null;
}
}
And this line:
而这一行:
Map<Integer, String> map = a.getMap();
gets you a warning now: "Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'
.
现在给你一个警告:"Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'
。
Even though the signature of getMap
is totally independent of T
, and the code is unambiguous regarding the types the Map
contains.
即使 的签名getMap
完全独立于T
,并且代码对于Map
包含的类型是明确的。
I know that I can get rid of the warning by reimplementing processA
as follows:
我知道我可以通过processA
如下重新实现来消除警告:
public <T> void processA(A<T> a) {
Map<Integer, String> map = a.getMap();
}
But why would I have to do that? What does T
matter here at all?
但我为什么要这样做呢?T
这里有什么关系?
So, the question is - why does type erasure have to not only affect T
(which is understandable - if I'm passing an instance of A
, T
is an unknown), but also "hardcoded" generic signature like <Integer, String>
in this case?
所以,问题是 - 为什么类型擦除不仅要影响T
(这是可以理解的 - 如果我传递A
,T
是一个未知的实例),而且像<Integer, String>
这种情况下一样“硬编码”通用签名?
采纳答案by Jatin
In your second case when you do:
在你做的第二种情况下:
public void processA(A a)
What do you mean by A
? Does it mean A<String>
or A<List<String>>
or what? You might not be using anything related to type of A
, but hey the compiler doesn't know this fact. To compiler, just A
is a sign of panic.
你是什么意思A
?这是否意味着A<String>
或者A<List<String>>
还是什么?您可能没有使用任何与类型相关的东西A
,但是编译器不知道这个事实。对于编译器来说,只是A
恐慌的标志。
In your case, because you dont specifically need to know the type of A, you can:
在您的情况下,因为您不需要特别了解 A 的类型,您可以:
public void processA(A<?> a) {
Map<Integer, String> map = a.getMap();
}
Having an argument type of A<?>
means, you do not specifically care the type of A
and just specify a wild card. To you it means: any object of A
with any type as its generic type would do. In reality, it means you do not know the type. Its useless because you cannot do anything related to A
in typesafe manner as ?
can be virtually anything!
有一个参数类型的A<?>
手段,你不特别关心的类型,A
只是指定一个通配符。对您而言,这意味着:任何A
类型的任何对象都可以作为其泛型类型。实际上,这意味着您不知道类型。它没用,因为你不能以A
类型安全的方式做任何与?
几乎任何事情相关的事情!
But as per your method body, it makes all the sense in the world to use A<?>
because no where in the body you actually need the type of A
但是根据您的方法主体,使用它在世界上是有意义的,A<?>
因为在主体中您实际上不需要类型A
回答by Dan Getz
When you mean to accept an A<T>
of any possible type T
, but don't need the T
, this is correctly expressed by using a wildcard and writing A<?>
. Doing so will get rid of the warning in your code:
当您打算接受A<T>
任何可能类型的T
,但不需要 时T
,这可以通过使用通配符和编写A<?>
. 这样做将消除代码中的警告:
public void processA(A<?> a) {
Map<Integer, String> map = a.getMap();
}
Using the bare type A
is not treated equivalently. As explained in the Java Language Specification, raw types like that are not intended to be used in new code:
使用裸类型A
不被同等对待。正如Java Language Specification 中所解释的,这样的原始类型不打算在新代码中使用:
Unchecked conversion is used to enable a smooth interoperation of legacy code, written before the introduction of generic types, with libraries that have undergone a conversion to use genericity (a process we call generification). In such circumstances (most notably, clients of the Collections Framework in java.util), legacy code uses raw types (e.g. Collection instead of Collection<String>). Expressions of raw types are passed as arguments to library methods that use parameterized versions of those same types as the types of their corresponding formal parameters.
Such calls cannot be shown to be statically safe under the type system using generics. Rejecting such calls would invalidate large bodies of existing code, and prevent them from using newer versions of the libraries. This in turn, would discourage library vendors from taking advantage of genericity. To prevent such an unwelcome turn of events, a raw type may be converted to an arbitrary invocation of the generic type declaration to which the raw type refers. While the conversion is unsound, it is tolerated as a concession to practicality. An unchecked warning is issued in such cases.
未经检查的转换用于启用在引入泛型类型之前编写的遗留代码与经过转换以使用泛型(我们称为泛型化的过程)的库之间的平滑互操作。在这种情况下(最值得注意的是 java.util 中集合框架的客户端),遗留代码使用原始类型(例如 Collection 而不是 Collection<String>)。原始类型的表达式作为参数传递给使用这些相同类型的参数化版本作为其相应形式参数的类型的库方法。
在使用泛型的类型系统下,此类调用不能被证明是静态安全的。拒绝此类调用将使大量现有代码无效,并阻止它们使用较新版本的库。这反过来又会阻止库供应商利用通用性。为了防止这种不受欢迎的事件转变,可以将原始类型转换为对原始类型所引用的泛型类型声明的任意调用。虽然这种转换是不健全的,但它作为对实用性的让步是可以容忍的。在这种情况下会发出未经检查的警告。