Java数组详解

张开发
2026/4/16 11:43:43 15 分钟阅读

分享文章

Java数组详解
Java 数组学习笔记目录1. 什么是数组2. 声明与初始化3. 内存模型重点4. 访问与遍历5. 常用操作与Arrays工具类6. 多维数组7. 常见异常与避坑指南8. 数组 vsArrayList9. 总结与最佳实践附录速查代码片段1. 什么是数组数组Array是 Java 中最基础的数据结构之一具有以下核心特征特征说明固定长度创建后长度不可变需提前指定同类型元素只能存放相同数据类型的值或同一父类/接口引用连续内存底层在堆内存中分配连续空间支持O(1)随机访问索引从 0 开始有效范围0~length-1对象类型数组本身是java.lang.Object的子类拥有clone()、length等成员2. 声明与初始化推荐语法// 声明int[]arr;// 推荐类型与变量名分离语义更清晰// int arr[]; // 兼容 C 风格不推荐// 静态初始化编译期确定元素int[]a{1,2,3};// 动态初始化只指定长度元素赋默认值int[]bnewint[5];// 默认值0// 混合写法int[]cnewint[]{4,5,6};// 注意new 后面不能写长度默认值规则数据类型默认值byte,short,int,long0float,double0.0char\u0000(空字符)booleanfalse引用类型String, 对象等nullJava 10 支持varvar nums new int[]{1, 2, 3};仅限局部变量3. 内存模型重点Java 数组在内存中的布局是理解其行为的关键栈内存 (Stack) 堆内存 (Heap) ┌──────────┐ ┌─────────────────────────┐ │ arr │───────▶ │ 数组对象 (Array Object) │ │ (引用变量)│ ├─────────────────────────┤ └──────────┘ │ length 3 │ ├─────────────────────────┤ │ [0] 10 │ │ [1] 20 │ │ [2] 30 │ └─────────────────────────┘arr是栈上的引用变量存储的是堆中数组对象的内存地址。数组对象包含length字段 实际元素数据。传参本质是值传递传递的是引用的副本修改元素会影响原数组但arr new int[]{}不会改变外部引用。voidmodify(int[]arr){arr[0]99;// 影响原数组arrnewint[1];// 仅改变局部引用不影响外部}4. 访问与遍历基础访问int[]arr{10,20,30};System.out.println(arr[0]);// 10arr.length;// 属性非方法返回 3遍历方式对比方式代码示例适用场景注意事项传统forfor(int i0; iarr.length; i)需要索引、修改元素最灵活增强forfor(int num : arr)只读遍历、代码简洁⚠️ 修改num不会改变原数组Arrays.toString()System.out.println(Arrays.toString(arr))调试打印仅限一维返回字符串// 增强 for 的陷阱int[]nums{1,2,3};for(intx:nums){x10;// ❌ 仅修改局部变量 xnums 不变}5. 常用操作与Arrays工具类Java 提供了java.util.Arrays工具类避免手写重复逻辑方法说明示例Arrays.sort(arr)排序基本类型双轴快排对象TimSortArrays.sort(arr);Arrays.binarySearch(arr, key)二分查找必须已排序int idx Arrays.binarySearch(arr, 20);Arrays.fill(arr, val)填充所有元素Arrays.fill(arr, 0);Arrays.copyOf(arr, newLen)扩容/缩容复制int[] copy Arrays.copyOf(arr, 5);Arrays.equals(a, b)内容相等比较非boolean eq Arrays.equals(a, b);Arrays.stream(arr)转 Stream APIJava 8Arrays.stream(arr).sum();高性能复制System.arraycopy()底层为native方法适合大数组批量复制。int[]src{1,2,3,4,5};int[]destnewint[5];System.arraycopy(src,1,dest,0,3);// 复制 src[1]~src[3] 到 dest[0]~dest[2]6. 多维数组Java 的“多维数组”本质是数组的数组支持规则矩阵与不规则锯齿数组。// 规则二维数组 3x4int[][]matrixnewint[3][4];// 锯齿数组每行长度不同int[][]jaggednewint[3][];jagged[0]newint[2];jagged[1]newint[4];jagged[2]newint[3];// 遍历二维数组for(inti0;imatrix.length;i){for(intj0;jmatrix[i].length;j){System.out.print(matrix[i][j] );}System.out.println();}️ 调试技巧System.out.println(Arrays.deepToString(matrix));7. 常见异常与避坑指南异常触发场景解决方案ArrayIndexOutOfBoundsException访问arr[length]或负索引严格校验边界优先使用增强 forNullPointerException数组引用为null时访问.length或元素初始化后再使用加判空逻辑ClassCastException泛型数组强转不当较少见避免创建泛型数组new T[10]误用arr1 arr2比较的是引用地址内容比较用Arrays.equals()防御性编程示例publicstaticvoidsafeAccess(int[]arr,intindex){if(arrnull)thrownewIllegalArgumentException(数组不能为 null);if(index0||indexarr.length){thrownewIndexOutOfBoundsException(索引越界);}// 安全操作...}8. 数组 vsArrayList维度数组 (Array)ArrayListE长度固定创建后不可变动态扩容默认 1.5 倍类型支持基本类型与引用类型仅支持引用类型自动装箱/拆箱有开销性能极高连续内存缓存友好略低内部仍是数组边界检查自动扩容API仅length无增删方法丰富的add/remove/contains等方法内存占用仅数据本身额外对象头、扩容冗余、包装类开销适用场景固定大小、性能敏感、基本类型存储频繁增删、长度未知、需集合操作转换技巧// 数组 → List固定大小不可 add/removeListIntegerlistArrays.asList(arr);// 数组 → 可变 ArrayListListIntegermutableListnewArrayList(Arrays.asList(arr));// List → 数组Integer[]arraylist.toArray(newInteger[0]);9. 总结与最佳实践何时使用数组数据量固定且已知追求极致性能如算法题、高频计算、基本类型批量处理作为底层数据结构如ArrayList、HashMap内部实现何时避免数组需要频繁插入/删除长度动态变化需要集合操作去重、过滤、排序等最佳实践清单优先使用int[] arr而非int arr[]遍历只读数据用增强for需索引用传统for比较内容用Arrays.equals()打印用Arrays.toString()避免在循环中反复new int[]提前分配或复用敏感场景使用System.arraycopy()替代手写循环多维数组注意判空与长度校验arr[i] ! null附录速查代码片段// 1. 快速初始化并打印int[]arr{5,2,9,1};System.out.println(Arrays.toString(arr));// [5, 2, 9, 1]// 2. 排序 二分查找Arrays.sort(arr);intposArrays.binarySearch(arr,5);// 返回索引// 3. 安全扩容推荐写法arrArrays.copyOf(arr,arr.length*2);// 4. 填充 批量复制int[]fullnewint[10];Arrays.fill(full,7);int[]partArrays.copyOfRange(full,2,6);// 索引 [2, 6)// 5. Stream 聚合求和intsumArrays.stream(arr).sum();intmaxArrays.stream(arr).max().getAsInt(); 数组是 Java 的基石建议配合 JVisualVM 观察堆内存布局或手写一遍ArrayList底层数组扩容逻辑能极大加深理解。 官方文档java.util.Arrays|System.arraycopy

更多文章