# 泛型 Uncompleted

如果一个方法接收List<Object>作为形式参数,那么如果尝试将List<String>的对象作为实际参数传进去,就会发现无法通过编译。尽管StringObject的子类,但是实际上会产生隐含的类型转换问题,所以编译器是禁止这样的行为的。

# 类型擦除

在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数会被编译器在编译的时候去掉,这个过程就叫做类型擦除。比如,List<String>List<Object>等类型在编译之后都会变成List。JVM看到的只有List,而由泛型附加的类型信息对于JVM来说是不可见的。

# 通配符

在使用泛型类的时候,既可以指定一个具体的类型,如List<String>就声明了具体类型是String类型;但也可以通过通配符?来表示未知类型,如List<?>就表示了List中包含的元素类型是未知的,也就意味着所有类型都是可以的。

但注意List<?>并不等同于List<Object>。因为List<Object>确定了List中包含的是Object及其子类,在使用的时候都可以通过Object来进行引用,而List<?>其中包含的元素是不确定的。如果其包含的是String类型的,那往里添加Integer类型的元素就是错误的。

在某些情况下,可以使用上下界来限制未知类型的范围。如通过List<? extends Number>来说明List中可能包含的元素类型是Number及其子类。而List<? super Number>则说明List中包含的是Number及其父类。当引入了上界之后,在使用类型的时候就可以使用上界类中定义的方法。