Java数组下标从0开始,本质是内存偏移量的直接映射;合法范围为0到length-1,越界访问抛ArrayIndexOutOfBoundsException,循环需用i<arr.length避免差一错误。
Java 数组下标从 0 开始,本质不是人为约定,而是直接对应内存中的偏移量(offset)。理解这一点,就能看懂为什么越界会报错、为什么循环容易写错、以及为什么几乎所有主流语言都这么设计。
下标就是偏移量
数组在内存中是一块连续空间,变量名(如 arr)实际存储的是首元素的地址(即基地址)。要访问第 i 个元素,JVM 计算的是:
- arr[i] 的地址 = 基地址 + i × 单个元素字节数
- i = 0 时,地址 = 基地址 + 0 → 正好是第一个元素的位置
- i = 1 时,地址 = 基地址 + 1 × 4(int 类型)→ 第二个元素
这个 i 就是“从首地址开始跳过几个单位”,它天然就是偏移量,而偏移量从 0 起算最直接。
为什么不能从 1 开始?
如果强行让下标从 1 开始,每次访问都要多一步减法运算:
立即学习“Java免费学习笔记(深入)”;
- arr[1] 地址 = 基地址 + (1 − 1) × 4 = 基地址
- arr[2] 地址 = 基地址 + (2 − 1) × 4 = 基地址 + 4
- ——每访问一次,CPU 都得多执行一条减法指令
看似微小,但在高频访问(如大数组遍历、图像处理、实时计算)中会累积成可观开销。零起点消除了这个冗余操作。
合法下标范围:0 到 length−1
数组的 length 是元素总数,不是最大下标:
- int[] a = new int[5]; → 有 5 个位置,下标只能是 0、1、2、3、4
- a[5] 或 a[−1] 都越界 → 运行时报 ArrayIndexOutOfBoundsException
- 二维数组同理:int[][] m = new int[3][4]; → 行下标 0~2,列下标 0~3
写循环时怎么避免出错?
牢记“下标从 0 起、长度是总数”这两个事实,就能避开常见差一错误:
- 标准 for 循环:for (int i = 0; i —— 条件用
<,不是 <=
- 倒序遍历:for (int i = arr.length − 1; i >= 0; i−−) —— 终止条件是
>= 0,不是 > 0
- 增强 for 循环(for (int x : arr))不暴露下标,适合只读场景,但底层仍依赖 0-based 机制