首页 > 解决方案 > 使用无界通配符会捕获错误但仅在使用原始类型时才会被标记为警告的情况

问题描述

以下是Maurice Naftalin 和 Philip Wadlerunbounded wildcard types对 vsraw types之间比较的引用。Java generics and collection

我们建议使用无界通配符类型而不是原始类型,因为它们提供了更强的静态类型保证;当您使用无界通配符时,许多被捕获为错误的错误只会在您使用原始类型时被标记为警告。

但是本书没有提供代码示例来解释这种情况。我想知道是否有人可以通过提供代码示例来添加解释?

标签: javagenericswildcardraw-types

解决方案


好吧,你可以改编同一章的一些例子来重现这种情况。

例如,考虑以下泛型类:

class Node<E> {
   private E value;
   @Override public String toString(){ return value.toString(); }
}

现在,假设您编写了以下代码,这是错误的:

Object o = new Node<Integer>(10);
Node<String> node = new Node<>("Hello");
if(o instanceof Node) {
  Node other = (Node) o;
  other.value = node.value; //Uh oh! Warning
}
System.out.println(node); //Hello
System.out.println(other); //Hello - WTH!

如果你尝试编译它,你只会得到一个警告,但它仍然可以编译得很好:

javac -Xlint:unchecked Node.java

Node.java:21: warning: [unchecked] unchecked assignment to variable value as member of raw type Node
            other.value = node.value;
                 ^
1 warning

但是,如果您更改代码以使用无界通配符:

Object o = new Node<Integer>(10);
Node<String> node = new Node<>("Hello");
if(o instanceof Node<?>) {
  Node<?> other = (Node<?>) o;
  other.value = node.value; //Uh oh! Compiler error
}

现在编译时会出现以下错误:

javac -Xlint:unchecked Node.java

Node.java:21: error: incompatible types: String cannot be converted to CAP#1
            other.value = node.value;
                              ^
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?
1 error

因此,正如您所见,无界通配符提供了比原始类型更好的类型检查保证。


推荐阅读