Java 数组 .length 详解:完整指南与示例
Source: Dev.to
Java 数组中的 .length 到底是什么?
在 Java 中,数组是一种容器对象,用来保存固定数量的同类型值。
.length 是一个 final 字段(而不是方法),它返回该容器的容量。
int[] myNumbers = new int[5]; // 创建一个拥有 5 个槽位的数组
System.out.println(myNumbers.length); // 输出:5
注意: 没有括号——
.length是属性,而不是方法。这常常让习惯使用String.length()的初学者感到困惑。
细节:.length 实际是如何工作的
Java 中的数组本身就是对象。实例化数组时,Java 会分配一块连续的内存并设置 .length 字段。该值不可更改,这也是数组大小固定的原因。
String[] playlist = new String[10]; // .length 现在是 10,且永远如此
playlist[0] = "Track 1";
playlist[9] = "Last track";
// 这个数组始终有 10 个槽位,无论我们实际填了多少
实际编码示例
示例 1:经典循环
// 处理游戏中的玩家得分
int[] highScores = {1250, 980, 1540, 720, 2100};
for (int i = 0; i < highScores.length; i++) {
System.out.println("Player " + (i + 1) + " score: " + highScores[i]);
}
始终使用 highScores.length 作为循环边界,以避免 ArrayIndexOutOfBoundsException。
示例 2:现代的 foreach 替代写法
// 使用增强的 for 循环更简洁
for (int score : highScores) {
System.out.println("Score: " + score);
}
增强的 for 循环内部会使用 .length,帮你省去手动的边界检查。
示例 3:验证数组容量
// 在手动管理数组时,添加元素前先检查容量
int[] dataBuffer = new int[1000];
int currentPosition = 0;
public void addData(int value) {
if (currentPosition < dataBuffer.length) {
dataBuffer[currentPosition++] = value;
} else {
System.out.println("Buffer full! Can't add more.");
}
}
常见陷阱与误区
陷阱 1:String 与数组的混淆
String name = "Java";
String[] languages = {"Java", "Python", "JavaScript"};
System.out.println(name.length()); // 方法 – 需要 ()
System.out.println(languages.length); // 字段 – 不要 ()
记忆技巧:数组 → 没有括号;String → 需要括号。
陷阱 2:空指针
int[] myArray = null;
System.out.println(myArray.length); // 抛出 NullPointerException!
在访问 .length 之前,务必先判断数组是否为 null。
陷阱 3:多维数组
int[][] matrix = new int[3][4];
System.out.println(matrix.length); // 3(行数)
System.out.println(matrix[0].length); // 4(第一行的列数)
.length 只返回第一维的大小。
专业技巧与最佳实践
为性能缓存 .length
int[] hugeArray = new int[1_000_000];
int length = hugeArray.length; // 缓存一次
for (int i = 0; i < length; i++) {
// 循环体
}
在紧密循环中缓存可以避免重复的字段访问。
用 .length 进行数组复制
int[] source = {1, 2, 3, 4, 5};
int[] destination = new int[source.length]; // 动态确定大小
System.arraycopy(source, 0, destination, 0, source.length);
防御式编程
public void processArray(int[] input) {
if (input == null || input.length == 0) {
// 及早处理边界情况
return;
}
// 主体逻辑
}
实际使用场景
场景 1:图像处理
// 处理像素数据(简化示例)
int[][] imagePixels = loadImage();
int height = imagePixels.length;
int width = imagePixels[0].length;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
imagePixels[y][x] = applyFilter(imagePixels[y][x]);
}
}
场景 2:游戏开发
// 管理游戏实体
Entity[] enemies = new Entity[MAX_ENEMIES];
int activeEnemies = 0;
public void updateGame() {
for (int i = 0; i < activeEnemies; i++) {
enemies[i].update();
}
}
场景 3:数据批处理
// 分块处理数据
int[] allData = fetchDatabaseRecords();
int batchSize = 100;
for (int i = 0; i < allData.length; i += batchSize) {
int end = Math.min(i + batchSize, allData.length);
processBatch(allData, i, end);
}
当数组(以及 .length)不足以满足需求时
虽然数组和 .length 是基础,但许多实际项目更倾向于使用 ArrayList 等集合来实现动态大小。不过,理解数组仍然很重要,因为:
- 旧代码常常使用原始数组。
- 集合内部是基于数组实现的。
- 性能关键的代码段仍可能直接使用数组。
常见问答
问: 创建数组后可以修改 .length 吗?
答: 不能。数组大小固定。如果需要动态大小,请使用可伸缩的集合(如 ArrayList)。
问: 数组的最大长度是多少?
答: Integer.MAX_VALUE - 5(约 21 亿),但受内存限制实际可用的要更小。
问: .length 是从 0 还是 1 开始计数?
答: 它返回总容量。长度为 5 的数组,合法索引为 0‑4。
问: .length 与 ArrayList.size() 有何区别?
答: .length 是数组的固定容量;size() 是可伸缩集合当前的元素数量。
问: 空数组的 .length 是多少?
int[] empty = new int[0];
System.out.println(empty.length); // 0 – 完全合法
结论
掌握 .length 字段是 Java 编程的基石。它提供了可靠的数组容量查询方式,帮助避免常见错误,并支撑许多性能关键的模式。熟练使用它,你就能自信地处理数组以及基于数组实现的集合。