Collections不能直接实例化,因其是私有构造函数的纯静态工具类,仅提供针对集合的通用操作方法。

为什么 Collections 不能直接实例化
Collections 是一个纯静态工具类,所有方法都是 static,构造函数被显式声明为 private。试图写 new Collections() 会触发编译错误:Constructor Collections() is not visible。
- 它不封装状态,只提供对
List、Set、Map(注意:Map相关方法在Collections中极少,主要靠Map自身或Map.of()等)的通用操作 - 所有方法都以集合对象为参数,例如
Collections.sort(list),而非list.sort()(后者是List接口默认方法,Java 8+) - 若误用
Arrays.asList()返回的不可变列表调用Collections.sort(),会抛出UnsupportedOperationException—— 因为底层是固定大小数组包装,不支持增删
Collections.unmodifiableXXX() 的真实行为
它返回的是原始集合的“只读视图”,不是深拷贝。底层仍引用原集合,一旦原集合被外部修改,只读视图也会反映变化(但无法通过只读视图修改)。
-
Collections.unmodifiableList(list)返回的List调用add()或set()会立即抛出UnsupportedOperationException - 但如果原
list在别处被修改(比如另一个引用调用了list.add(x)),那么只读视图的get(0)可能返回新值 - 真正安全的只读封装需配合不可变数据结构(如
ImmutableList.copyOf(list)来自 Guava)或手动复制:Collections.unmodifiableList(new ArrayList(original))
排序与同步包装器的实际限制
Collections.sort() 和 Collections.synchronizedList() 这类方法返回的是装饰器(Decorator)对象,使用时容易忽略其副作用边界。
-
Collections.sort()要求元素实现Comparable,否则必须传入Comparator;若元素为null且比较器未处理null,会抛NullPointerException -
Collections.synchronizedList(list)仅保证单个方法调用线程安全(如sList.get(0)是原子的),但复合操作(如if (!sList.isEmpty()) sList.remove(0))仍需手动加锁,否则存在竞态 - 同步包装器性能开销明显,高频场景优先考虑
CopyOnWriteArrayList(读多写少)或ConcurrentHashMap替代Collections.synchronizedMap()
空集合与单元素集合的正确创建方式
避免手写 new ArrayList() 再 add(),既低效又易错。应优先使用 Collections 提供的不可变工厂方法。
立即学习“Java免费学习笔记(深入)”;
- 空集合:
Collections.emptyList()、Collections.emptySet()、Collections.emptyMap()—— 返回共享的、类型安全的不可变实例,零内存开销 - 单元素集合:
Collections.singletonList("a")、Collections.singleton("x")、Collections.singletonMap("k", "v")—— 同样不可变,且比Arrays.asList("a")更明确语义 - ⚠️ 注意:
Collections.singletonList()返回的是List,不是ArrayList;调用list.add()会抛异常,不是因为“没初始化”,而是设计如此
String s = "hello"; List很多开发者卡在“明明用了safeList = Collections.singletonList(s); // 下面这行会抛 UnsupportedOperationException // safeList.add("world");
unmodifiableList 却还是被改了”,问题往往出在没意识到原集合仍可变;或者以为 synchronizedList 能包治并发,结果在迭代时忘了加锁 —— 这些都不是 API 设计缺陷,而是对装饰器模式边界的误判。










