商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 怎么利用 Collections.checkedList() 装饰现有列表以防止在运行时插入非法类型的对象

怎么利用 Collections.checkedList() 装饰现有列表以防止在运行时插入非法类型的对象

  发布于2026-07-10 阅读(0)

扫一扫,手机访问

先来说一个很多人容易忽略的细节:Collections.checkedList() 不会去修改你原来的列表,它只是返回一个包装器。原列表该怎么用还怎么用——如果你不把所有写操作都引导到这个包装引用上,那类型安全就是一句空话。换句话说,它只管自己这扇门,不管旁边的窗户有没有关好。

怎么利用 Collections.checkedList() 装饰现有列表以防止在运行时插入非法类型的对象

为什么 Collections.checkedList() 不能直接“加固”已有列表

说白了,它不修改原列表,而是返回一个新包装器对象——原列表依然裸奔。任何绕过包装器的写入(比如直接调用原列表的 add())都不会被检查。你必须确保所有写操作都走这个包装后的引用,否则类型安全形同虚设。

  • 原列表(如 new ArrayList())本身没有泛型运行时约束,JVM 允许 rawList.add(new Integer(42))
  • Collections.checkedList(rawList, String.class) 返回的是 CheckedList 实例,它在 add()set()addAll() 等方法里插入前做 instanceof 检查。
  • 如果同时持有原始引用和包装引用,混着用,就等于给自己留了后门。

正确初始化和使用 checkedList 的典型写法

最稳妥的方式是:从创建起就只暴露包装后的引用,原列表要么私有化,要么直接丢掉。

List safeList = Collections.checkedList(
    new ArrayList<>(), 
    String.class);
  • 别写成 ArrayList raw = new ArrayList<>(); List safe = Collections.checkedList(raw, String.class); —— 因为 raw 依然可用,等于留了个后门。
  • 传入的 Class 参数必须和你要的类型严格匹配;比如用 String.class 包装 ArrayList 不会报错,但后续 add("hello")` 一调用马上抛 ClassCastException
  • 包装器对 get()size() 等读操作没有额外开销,写操作只多一次类型判断,性能影响可以忽略不计。

checkedList 对哪些操作做检查?哪些不检查?

它只拦截那些明确可能引入非法对象的写方法,并不是什么都管。

  • ✅ 检查:add()set()addAll()retainAll()(注意 removeAll() 呢?它其实不检查要移除的元素是否匹配,它只防止因操作意外注入非法类型)。
  • ❌ 不检查:get()iterator()listIterator() 返回的迭代器本身——不过这些迭代器上的 set()add() 方法会被检查。
  • ⚠️ 特别提醒:toArray() 不检查,但返回的数组类型由运行时实际内容决定。要是原列表被污染了(比如有人绕过包装器塞了一个 Integer),那 toArray(String[].class) 会直接抛出 ArrayStoreException

和泛型擦除、ClassCastException 的关系

这个东西不是编译期类型系统的一部分,它是在运行时补一层防御——所以它只能防“写入时类型不符”,防不了所有类型错误。

  • 编译器允许 safeList.add((Object)42)(因为泛型在运行时已经擦除了),但到了运行时 checkedList 会立刻抛 ClassCastException
  • 它防不了反射绕过(比如通过 Field.setAccessible(true) 直接改底层数组),也防不了序列化/反序列化污染。
  • 如果底层列表本身是不可变的(比如 Collections.emptyList()),checkedList() 会包装成功,但所有写操作都会立即失败——这有时是故意为之,用来构建带类型校验的只读契约。

说到底,真正起作用的前提是:你把包装后的引用当作唯一的入口来使用。一旦原始引用泄露,或者混用原始列表,这个防护就形同虚设。它解决的是“不小心写错类型”的问题,不是“恶意破坏”的问题。

本文转载于:https://www.php.cn/faq/2399147.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注