通配符?用于解决java集合类型不兼容问题,表示未知具体类型,支持只读操作;? extends t限定上界,安全读取t或其子类元素。

通配符 ? 是为了解决集合类型不兼容问题
Java 集合不是协变的:哪怕 Student 继承自 Person,ArrayList<student></student> 也不能直接赋值给 ArrayList<person></person> 参数。编译器会报错,因为泛型在编译期是严格类型检查的。
这时用 Collection> 就能绕过限制——它表示“某个确定但未知的类型”,允许传入 ArrayList<string></string>、LinkedList<integer></integer> 等任意具体参数化的集合。
- 只能调用
Object的方法(比如toString()、hashCode()),不能调用子类特有方法 - 不能往里
add()任何元素(除了null),因为编译器不知道该加什么类型 - 适合只读场景,比如遍历、统计、打印
? extends T 用于安全地读取上界类型元素
当你需要从集合中取出元素,并统一按 T 或其父类来处理时,用上限通配符。例如:所有 Number 子类(Integer、Double)的集合,都可传给 processNumbers(Collection extends Number>)。
-
it.next()返回的是Number类型,可以安全调用doubleValue()、intValue()等 - 仍然禁止
add()(除了null),因为具体子类型不确定,加Integer可能破坏Collection extends Double>的语义 - 常见于工具方法:求和、最大值、转换为数组等只读聚合操作
? super T 用于安全地写入下界类型元素
当你需要往集合里塞 T 或其子类实例,并且希望方法能接受尽可能宽泛的集合类型时,用下限通配符。例如:一个方法要往集合里添加 String,那它应该能接受 Collection<object></object>、Collection<charsequence></charsequence>、甚至 Collection<string></string>。
- 可以安全调用
add(new String("x"))、add(new StringBuilder())(只要它们是T的子类) - 但
it.next()只能当作Object用——因为你不知道集合实际装的是Object还是CharSequence,返回类型最保守就是Object - 典型应用:
Collections.copy(dest, src)中dest参数声明为Collection super T>
别把 <t></t> 和 ? 混成一回事
<t></t> 是类型参数声明,出现在方法签名或类定义开头,代表一个可被多次引用、参与类型推导的具体类型;而 ? 是通配符,只在使用位置出现,表示“此处类型已固定但不可知”。
-
public static <t> void sort(List<t> list)</t></t>:支持类型推导,T在整个方法体里一致可用 -
public static void print(Collection> c):不关心具体类型,也不需要操作它,只做通用遍历 - 错误写法:
void addAll(Collection> dest, Collection> src)—— 两个?彼此无关,无法保证src元素能放进dest;应改用<t> void addAll(Collection super T> dest, Collection<t> src)</t></t>
?,编译器就按“最弱契约”约束你——能读多少、能写多少,全由上下界决定。没想清楚读写意图就硬套 ?,轻则编译失败,重则运行时类型异常藏得极深。










