java中泛型上限通配符? extends type用于“只读”场景,允许安全读取number及其子类实例但禁止写入(除null),典型如sumandprint(list

Java 中泛型通配符上限用 ? extends Type 表示,核心作用是让方法或变量能安全接收某类型及其所有子类的泛型实例,但只允许读取、禁止写入(除 null 外)。
什么时候该用 ? extends Type
当你设计一个“只从集合中取数据”的方法时,就适合用上限通配符。它让方法更通用,比如一个打印数字的方法,既要支持 List<integer></integer>,也要支持 List<double></double> 和 List<number></number>,而不用为每种类型写重载。
- 典型场景是“生产者”:容器提供数据,你消费它
- 常见于工具方法参数,如
printNumbers(List extends Number>) - 不能用于需要添加元素的逻辑,否则编译不通过
怎么写才合法
声明和使用必须匹配语义:能读,不能写。
- 声明示例:
List extends Number> list = new ArrayList<integer>();</integer> - 读取安全:
Number n = list.get(0);—— 返回值自动向上转型为Number - 写入非法:
list.add(42);或list.add(new Double(3.14));都会报编译错误 - 唯一允许的写入是
null:list.add(null);(极少用,通常应避免)
为什么不能添加元素
因为编译器只知道它是 Number 或其某个子类,但不知道具体是哪一个。比如你传入的是 List<integer></integer>,若允许 add(new Double(1.0)),就会破坏类型一致性。JVM 运行时泛型已擦除,这个限制全靠编译器在编译期强制保障。
- 类型安全靠编译器推断,不是靠运行时检查
- 即使你确定传入的是
ArrayList<integer></integer>,语法上也不允许调用add() - 想写入?改用具体类型(如
List<integer></integer>)或下界通配符? super Integer
实际小例子
下面这个方法可以处理任意数字列表:
public static void sumAndPrint(List extends Number> numbers) {
double sum = 0.0;
for (Number n : numbers) {
sum += n.doubleValue();
}
System.out.println("Sum: " + sum);
}
调用时完全自由:
-
sumAndPrint(Arrays.asList(1, 2, 3));//List<integer></integer> -
sumAndPrint(Arrays.asList(1.5, 2.7));//List<double></double> -
sumAndPrint(new ArrayList<number>());</number>//List<number></number>
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











