collection是集合顶层接口,不能实例化,只定义add、remove等共性方法;list允许重复且有序,set禁止重复且无序,二者虽同继承collection但约束不同、不可互转;toarray()返回object[]因泛型擦除,安全写法是传入目标类型数组。

Collection 不是具体类,不能直接 new Collection();它只是定义单列集合共性行为的契约,所有子接口(List、Set、Queue)和实现类(ArrayList、HashSet、LinkedList)都必须遵守这套规则。
Collection 接口本身不提供具体实现
它只声明方法,比如 add(E)、remove(Object)、contains(Object)、size() 等。这些方法在不同子类中语义一致,但行为可能完全不同:
-
ArrayList.add()是在数组末尾追加,平均 O(1),最坏 O(n)(触发扩容) -
LinkedList.add()是链表尾插,稳定 O(1) -
HashSet.add()先算 hash、再判重复、最后插入,平均 O(1),最坏 O(n)(哈希冲突严重时)
你写 Collection<string> c = new ArrayList();</string>,调用的是 ArrayList 的实现,不是 Collection 的——因为接口里根本没有方法体。
为什么 List 和 Set 都继承 Collection 却互不兼容
关键在「约束条件」不同,而 Collection 接口无法表达这些差异:
-
List允许重复 + 保证插入顺序 + 支持索引访问(get(int)不在Collection中) -
Set禁止重复 + 不保证顺序(HashSet)或按插入顺序(LinkedHashSet),也没有索引概念 - 两者都实现了
Collection,所以都能用add()、size()、iterator(),但一旦需要get(0)或add(1, "x"),就必须转型为List
试图把 Set 强转成 List 会抛 ClassCastException;反过来也不行——类型系统在这里是严格的,不是“看起来像就能用”。
toArray() 方法为什么返回 Object[] 而不是 E[]
这是泛型擦除导致的典型陷阱:
-
Collection<string>.toArray()</string>声明返回Object[],不是String[] - 直接强转
(String[]) c.toArray()在运行时可能失败(当底层实际是Object[]且含非String元素时) - 安全写法是传入带类型的数组:
c.toArray(new String[0]),JVM 会根据参数类型返回正确泛型数组
这个细节常被忽略,但在线上环境遇到 ArrayStoreException 或 ClassCastException 时,往往就卡在这里。
真正容易被忽略的,是把 Collection 当作“能装一切集合的万能容器”来用——它确实能引用所有单列集合,但一旦脱离其定义的方法范围(比如想排序、想查第几个、想保持唯一性),就必须明确知道背后实际是哪个子类型,否则编译过、运行崩。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











