arrays是不可实例化的工具类,其核心方法围绕原数组不可变设计:sort修改原数组,copyof新建数组;排序采用双轴快排或timsort,binarysearch要求手动预排序,aslist返回受限list。

掌握Arrays工具类的核心方法,关键不在死记API,而在理解每个方法解决什么问题、为什么这样设计、以及底层如何权衡性能与语义。它不是一堆静态方法的堆砌,而是一套针对数组操作痛点的系统性解决方案。
理解Arrays的设计定位:为什么不能new,且全是static
Arrays是典型的不可实例化工具类——私有构造、final修饰、无状态。这背后是明确的设计契约:
- 数组操作天然无状态,不需要维护实例字段,static方法最轻量
- 禁止new避免误用(比如误以为能缓存排序结果),强制用户聚焦“一次操作、一个目的”
- 所有方法都围绕“原数组不可变”前提展开:sort会修改原数组,copyOf则新建,语义清晰不混淆
抓住三类核心方法的底层逻辑主线
不必逐行读完全部源码,但需吃透三组方法的设计动机与实现选择:
- 排序(sort / parallelSort):基本类型用DualPivotQuicksort(双轴快排)+ 小数组切回插入排序;对象数组用Timsort(归并+插入混合)。区别在于稳定性需求——数字排序不关心相等元素顺序,对象排序常需保持原始相对位置
- 查找(binarySearch):只对已排序数组有效,源码本质是标准二分循环,返回下标或负插入点(-(low + 1))。注意它不校验是否真已排序,出错由调用方负责
- 比较与转换(equals / deepEquals / asList / toString):equals做逐元素浅比较;deepEquals递归处理多维数组;asList返回的是Arrays内部的ArrayList(非java.util.ArrayList),不支持add/remove,只为快速桥接集合API
重点看懂几个典型方法的源码关键细节
动手看几段精要代码,比泛读更高效:
- toString():用StringBuilder拼接,先判null再判空数组,循环中用逗号分隔,末尾补]——这是JDK里最经典的数组格式化范式
- fill():简单for循环赋值,但支持区间填充(fromIndex到toIndex-1),边界检查严格,避免越界
- copyOf():本质是System.arraycopy()封装,底层调用JVM本地方法,比手动循环快得多;newLength小于原长则截断,大于则补默认值(0/false/null)
避开常见认知误区
很多开发者卡在似懂非懂的环节,其实是被表象误导:
- asList传int[]得到的是一个装了int[]对象的单元素List,不是三个Integer——因为泛型擦除+基本类型无法作为T,实际传入的是数组引用本身
- binarySearch前必须手动sort,它不做预检;parallelSort也不是“一定更快”,小数组反而有线程开销,阈值由MIN_ARRAY_SORT_GRAN决定
- equals比较两个null数组返回true,但比较null和非null数组抛NullPointerException——这符合Object.equals约定,不是bug
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











