java中arraylist

Java 中使用泛型上限通配符(? extends T)声明的 ArrayList,比如 ArrayList extends Number>,**只能读取数据,不能添加(除 null 外)**。读取时,元素类型被安全地视为上界类型 T 或其父类。
为什么只能读不能写?
上限通配符表示“某种具体的、未知的 T 的子类型”。编译器无法确认你添加的对象是否属于那个“未知的具体子类型”,所以禁止写入(防止类型污染)。但读取是安全的——无论实际是 Integer、Double 还是 BigDecimal,它们都一定是 Number 或其子类,可以向上转型为 Number。
如何正确读取数据?
从 ArrayList extends Number> 中读出的每个元素,可直接赋值给 Number 类型变量,也可安全调用 Number 及其父类(如 Object)的方法:
-
✅ 正确读取:
Number n = list.get(0);Object obj = list.get(0);System.out.println(list.get(0).doubleValue());(因为doubleValue()是Number的方法) -
❌ 错误写入:
list.add(new Integer(1));→ 编译错误list.add(new Object());→ 编译错误(Object不是Number的子类)
常见误用与替代方案
如果既要读又要写,说明设计上不适合用上限通配符:
- 需要统一操作子类型对象(只读场景)→ 用
? extends T,如处理各种数字列表、不同形状的图形集合 - 需要向集合添加具体子类型对象 → 改用具体泛型,如
ArrayList<integer></integer>或ArrayList<number></number> - 需要写入任意子类型且保持灵活性 → 考虑下限通配符
? super T(适用于消费者场景,如addAll),但它不支持安全读取为T
一个实用例子
假设你有多个数字列表:
ArrayList<integer> ints = new ArrayList(Arrays.asList(1, 2, 3));
ArrayList<double> doubles = new ArrayList(Arrays.asList(1.1, 2.2));
// 安全地将它们传给只读方法
printSum(ints); // OK
printSum(doubles); // OK
static void printSum(ArrayList extends Number> numbers) {
double sum = 0.0;
for (Number n : numbers) { // ✅ 自动推断为 Number 类型
sum += n.doubleValue();
}
System.out.println("Sum = " + sum);
}</double></integer>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











