java 中通配符的类型擦除如何工作?

ove*_*nge 5 java generics javac

正如javadoc中提到的,

如果类型参数无界,则将泛型类型中的所有类型参数替换为其边界或对象。因此,生成的字节码仅包含普通的类、接口和方法。

如有必要,请插入类型转换以保持类型安全。

我了解以上两点,这些点是使用和javac等类型参数来处理的。T<K, V>

但对于以下方法中的通配符,

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}    

public void sumOfNumbers(List<? extends Number> numbers){
        double d = 0.0;
        for(Number n: numbers){
            d += n.doubleValue();
        }
        System.out.println(d);
    }
Run Code Online (Sandbox Code Playgroud)

如果出现外卡,

1)

如何javac处理这些通配符?它会用什么东西代替吗?

2)

如何执行类型转换?

Jac*_*cko 1

?被替换为Object(因为它没有界限) - 没那么有用。
在构建时,编译器将检查您是否仅调用对象的行为。

? extends Number被替换为它的边界Number
在构建时,编译器将检查您是否仅将一个Number或其任何子类型作为参数传递。

演员阵容- 没有演员阵容。在构建时,编译器将检查您是否仅调用Number.

T替换为您为该类的类型参数提供的任何类型。
在构建时,编译器将检查您是否仅传递一个类型T作为参数(T在您的方法中用作参数)。

?并且T有不同的用途。
考虑T泛型类型(类、接口)创建 - 然后可以在类型中的任何位置引用。

可以将其视为?限制在编译时可以合法调用方法的类型的一种方式。

  • “强制转换 - 不强制转换。”这并不完全正确,必要时会对绑定类型进行运行时类型检查。 (2认同)