源本科技 | 码上会

Java 数组声明与初始化

2025/12/25
24
0

学习目标

  • 掌握 Java 数组的两种声明语法及其区别

  • 熟练使用静态、动态、循环和 Stream 四种初始化方式

  • 能够安全地访问数组元素并获取其长度

  • 理解数组在内存中的分配机制


数组的声明

在 Java 中,声明数组仅创建一个引用变量,并不分配实际存储空间。必须通过初始化才能使用。

两种等效的声明语法

// 推荐写法:类型后加 []
int[] numbers;

// 兼容 C 风格:变量名后加 []
int numbers[];

最佳实践:优先使用 int[] arr 形式,语义更清晰(“这是一个整型数组”)。

常见类型声明示例

int[] scores;           // 整型数组
double[] prices;        // 双精度浮点数组
boolean[] flags;        // 布尔数组
String[] names;         // 字符串对象数组
Student[] students;     // 自定义类对象数组

数组的初始化方式

静态初始化(编译时已知值)

在声明时直接提供所有元素值,无需指定大小,编译器自动计算长度。

// 整型数组
int[] numbers = {10, 20, 30, 40, 50};

// 字符串数组
String[] fruits = {"苹果", "香蕉", "芒果"};

// 空数组(合法)
int[] empty = {};

优点:简洁直观,适用于元素数量少且固定的场景。


动态初始化(运行时分配内存)

先用 new 分配指定大小的内存,再逐个赋值。

// 创建长度为 5 的整型数组(默认值:0)
int[] numbers = new int[5];

// 手动赋值
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

内存分配特点:

  • 基本类型:元素自动初始化为默认值(0, false, 0.0

  • 引用类型:元素初始化为 null


使用循环批量初始化

适合生成连续或有规律的数据。

// 初始化为 1 到 5
int[] arr = new int[5];
for (int i = 0; i < arr.length; i++) {
    arr[i] = i + 1;  // arr = [1, 2, 3, 4, 5]
}

// 初始化为平方数
int[] squares = new int[4];
for (int i = 0; i < squares.length; i++) {
    squares[i] = (i + 1) * (i + 1); // [1, 4, 9, 16]
}

使用 Stream 初始化(高级)

利用 IntStream 提供函数式编程风格的初始化方式。

range(start, end) —— 左闭右开

int[] arr1 = java.util.stream.IntStream.range(1, 5).toArray();
// 结果: [1, 2, 3, 4]

rangeClosed(start, end) —— 两端闭合

int[] arr2 = java.util.stream.IntStream.rangeClosed(1, 4).toArray();
// 结果: [1, 2, 3, 4]

of(...) —— 指定具体值

int[] arr3 = java.util.stream.IntStream.of(5, 10, 15).toArray();
// 结果: [5, 10, 15]

优势:代码简洁、可链式操作,适合复杂数据生成逻辑。


访问数组元素

基本访问

int[] arr = {1, 2, 3, 4};

// 读取第一个元素
System.out.println(arr[0]); // 输出: 1

// 修改第三个元素
arr[2] = 99;

获取数组长度

System.out.println("数组长度: " + arr.length); // 输出: 4

重要规则

  • 索引范围:0length - 1

  • 越界访问(如 arr[4])会抛出 ArrayIndexOutOfBoundsException


综合演示

public class ArrayDemo {
    public static void main(String[] args) {
        // 1. 静态初始化
        int[] numbers = {10, 20, 30, 40, 50};
        
        // 2. 遍历输出
        System.out.println("数组元素为:");
        for (int i = 0; i < numbers.length; i++) {
            System.out.println(numbers[i]);
        }
        
        // 3. 直接访问首元素
        System.out.println("第一个元素是: " + numbers[0]);
        
        // 4. 使用 Stream 初始化新数组
        int[] sequence = java.util.stream.IntStream.rangeClosed(1, 3).toArray();
        System.out.print("Stream 生成的数组: ");
        for (int val : sequence) {
            System.out.print(val + " ");
        }
    }
}

输出:

数组元素为:
10
20
30
40
50
第一个元素是: 10
Stream 生成的数组: 1 2 3 

内存分配说明

无论采用哪种初始化方式,Java 数组的内存都在堆(Heap)上分配,这是与 C/C++ 的关键区别:

  • int[] arr = new int[5]; → 在堆中分配 5 个 int 的连续空间

  • int[] arr = {1,2,3}; → 编译器自动转换为 new int[]{1,2,3}


重点总结

操作

语法

特点

声明

int[] arr;

仅创建引用,未分配内存

静态初始化

int[] a = {1,2,3};

编译时确定值,自动计算长度

动态初始化

int[] a = new int[5];

运行时分配,元素为默认值

循环初始化

for 赋值

适合有规律数据

Stream 初始化

IntStream.of(...).toArray()

函数式风格,代码简洁

访问元素

arr[index]

索引从 0 开始

获取长度

arr.length

返回元素个数


思考题

  1. 以下两种写法有何区别?哪种更推荐?

    int[] list1 = new int[]{1, 2, 3};
    int[] list2 = {1, 2, 3};
  2. 如果你有一个长度为 n 的数组,如何用一行代码将其所有元素初始化为 7?(提示:可使用 Arrays.fill()

  3. 在性能敏感的场景下,for 循环和 IntStream 初始化哪种更快?为什么?