简体   繁体   English

未经检查的分配警告

[英]Unchecked assignment warning

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>在这种情况下?

In your second case when you do: 在你的第二种情况下:

public void processA(A a)

What do you mean by A ? A是什么意思? Does it mean A<String> or A<List<String>> or what? 这是指A<String>还是A<List<String>>还是什么? You might not be using anything related to type of A , but hey the compiler doesn't know this fact. 您可能没有使用与A类型相关的任何内容,但是编译器不知道这个事实。 To compiler, just A is a sign of panic. 对于编译器,只是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. 参数类型为A<?>意味着,您没有特别关注A的类型,只需指定一个外卡。 To you it means: any object of A with any type as its generic type would do. 对你而言,它意味着:任何类型的A作为其泛型类型的任何对象都可以。 In reality, it means you do not know the type. 实际上,这意味着你不知道这种类型。 Its useless because you cannot do anything related to A in typesafe manner as ? 它没用,因为你不能以类型安全的方式做任何与A有关的事情? can be virtually anything! 可以是几乎任何东西!

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的类型

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<?> . 当你的意思是接受任何可能类型TA<T>但不需要T ,可以通过使用通配符并写入A<?>来正确表达。 Doing so will get rid of the warning in your code: 这样做将消除代码中的警告:

public void processA(A<?> a) {
    Map<Integer, String> map = a.getMap();
}

Using the bare type A is not treated equivalently. 使用裸A类型不会被等效地处理。 As explained in the Java Language Specification , raw types like that are not intended to be used in new code: 正如Java语言规范中所解释的那样,这样的原始类型不打算在新代码中使用:

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 (eg Collection instead of Collection<String>). 在这种情况下(最值得注意的是,java.util中的Collections Framework的客户端),遗留代码使用原始类型(例如Collection而不是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. 在这种情况下会发出未经检查的警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM