通配符?后只允许出现一个边界。
通配符只允许出现在引用中(普通变量引用、形参),一般是用作<? extends 具体类型>或者<? super 具体类型>。相对地,比如通配符不允许出现在泛型定义中(泛型类、泛型接口、泛型方法的< >里),class one<? extends Integer> {}这样是不允许的,类定义时继承泛型类时的< >里也不可以出现。在泛型类或泛型方法的{ }里还有泛型方法的形参上,配合占位符,甚至可以使用? extends T或者? super T这种形式来用作引用。
在new泛型类的时候也不可以使用通配符,比如new ArrayList<?>()。泛型方法的显式类型说明也不可以使用通配符。
数组协变
具体讲通配符之前,有必要先讲一下数组协变。数组协变可以理解为多态,即子类对象数组可以向上转型为父类对象数组的引用。由于java里的数组在初始化后一定会记住元素的类型,虽然数组协变会带来一些问题(下例就会演示),但有了数组的运行时元素插入的类型检查保护,使得造成的问题不会那么严重。所以即使数组可以协变,它也是足够安全的。
从历史原因上讲,是因为JDK1.0的时候没有设计出真正的泛型(像C++的模板,运行时也可以获得类型参数的真正类型),但当时又有着通用数组的需求(比如,底层实现为数组的容器类)。 |
|