未经检查的分配警告

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 是一个未知数),还有 "hardcoded" 通用签名,例如 <Integer, String> 在这种情况下?

当您想要接受任何可能类型 TA<T>,但不需要 T 时,可以使用通配符并编写 [=] 来正确表达14=]。这样做将消除代码中的警告:

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

使用裸类型 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.

在你的第二种情况下,当你这样做时:

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

的类型