使用无限通配符会捕获错误的情况,但只有在使用原始类型时才会被标记为警告

situations where an error will be caught by using unbounded wildcards, but will only be flagged as a warning if you use raw type

下面是 Maurice Naftalin 和 Philip Wadler 对 unbounded wildcard typesraw types 的比较引述,来自 Java generics and collection

We recommend using unbounded wildcard types in preference to raw types because they provide stronger static typing guarantees; many mistakes that are caught as an error when you use unbounded wildcards will only be flagged as a warning if you use raw types.

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

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

例如,考虑以下泛型 class:

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

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