Java 数组的定义与使用

一、数组的基本概念

1.1为什么需要数组

在处理多个相同类型的数据时,如果逐个创建变量,会显得非常繁琐。例如,要存储 5 个学生的成绩,我们可能需要创建 5 个 int 类型的变量;但如果有 100 个学生,就需要创建 100 个变量,这显然不利于代码的编写和维护。而数组的出现,正是为了解决这一问题,它可以将多个相同类型的数据集中存储在一段连续的内存空间中。

1.2什么是数组

数组可以看作是相同类型元素的一个集合,在内存中占据一段连续的空间。这就好比现实中的车库,多个车位连续排列,每个车位都有自己的编号。数组具有以下特点:

  • 数组中存放的元素类型相同;
  • 数组的空间是连续的;
  • 每个空间都有自己的编号,即数组的下标,起始下标为 0

1.3数组的创建及初始化

1.3.1数组的创建

数组的创建语法为:T[] 数组名 = new T[N],其中 T 表示数组中存放元素的类型,T [] 表示数组的类型,N 表示数组的长度。例如:

int[] array1 = new int[10]; // 创建一个可以容纳10个int类型元素的数组
double[] array2 = new double[5]; // 创建一个可以容纳5个double类型元素的数组

1.3.2数组的初始化

数组的初始化主要分为动态初始化和静态初始化两种方式:

  • 动态初始化:在创建数组时,直接指定数组中元素的个数。例如:int[] array = new int[10];
  • 静态初始化:在创建数组时不直接指定数据元素个数,而是直接将具体的数据内容进行指定。语法格式为:T[] 数组名称 = {data1, data2, data3, ..., datan};。例如:
int[] array1 = new int[]{0,1,2,3,4,5,6,7,8,9};
double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};

静态初始化还有一种简写方式,可以省去后面的new T[],编译器在编译时会自动还原。

此外,数组初始化还有一些注意事项:

  • 静态初始化时,{}中数据类型必须与[]前数据类型一致;
  • 静态和动态初始化可以分为两步,但静态初始化的省略格式不可以拆分,否则会编译失败;
  • 如果没有对数组进行初始化,数组中元素会有其默认值。对于基本类型,默认值根据类型不同而有所差异,如 int 类型的默认值为 0,boolean 类型的默认值为 false 等;如果数组中存储的是引用类型元素,默认值为 null

二、数组的使用

2.1数组中元素的访问

数组在内存中是一段连续的空间,空间的编号从 0 开始依次递增,这个编号称为数组的下标。我们可以通过下标来访问数组中任意位置的元素,也可以通过下标修改数组中的元素。例如:

int[] array = new int[]{10, 20, 30, 40, 50};
System.out.println(array[0]); // 访问数组中下标为0的元素,输出10
array[0] = 100; // 修改数组中下标为0的元素的值
System.out.println(array[0]); // 输出修改后的值100

需要注意的是,数组的下标范围是[0, N)(N 为数组的长度),不能越界,否则会抛出ArrayIndexOutOfBoundsException异常。

2.2遍历数组

遍历数组是指将数组中的所有元素都访问一遍。常见的遍历方式有两种:

2.2.1使用 for 循环遍历

我们可以通过数组的长度(数组名.length)来控制循环的次数,从而遍历数组中的每个元素。例如:

int[] array = new int[]{10, 20, 30, 40, 50};
for(int i = 0; i < array.length; i++){
    System.out.println(array[i]);
}

这种方式的好处是可以通过下标对数组元素进行修改.

2.2.2使用 for-each 遍历

for-each 是 for 循环的另外一种使用方式,它能够更方便地完成对数组的遍历,并且可以避免循环条件和更新语句写错。例如:

int[] array = {1, 2, 3};
for (int x : array) {
    System.out.println(x);
}

不过,for-each 遍历无法直接通过下标修改数组元素的值。

2.2.3使用 Arrays工具类遍历
int[] array={1,2,3,4,5};
        String arr=Arrays.toString(array);
        System.out.println(arr);

三、数组是引用类型

3.1JVM 的内存分布

内存是程序运行时存储数据的地方,JVM 将内存按照功能的不同进行了划分,主要包括以下几个部分:

  • 程序计数器:一个很小的空间,用于保存下一条执行的指令的地址;
  • 虚拟机栈:与方法调用相关,每个方法执行时会创建一个栈帧,栈帧中包含局部变量表、操作数栈等信息,方法运行结束后栈帧销毁;
  • 本地方法栈:与虚拟机栈作用类似,用于保存 Native 方法的局部变量;
  • :JVM 管理的最大内存区域,使用 new 创建的对象都存储在这里,堆中的数据只要还在被使用就不会被销毁;
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量等数据。

3.2基本类型变量与引用类型变量的区别

  • 基本数据类型创建的变量(基本变量),其空间中直接存放的是对应的值;
  • 引用数据类型创建的变量(对象的引用),其空间中存储的是对象所在堆空间的地址。

例如,在以下代码中:

public static void func() {
    int a = 10;
    int b = 20;
    int[] arr = new int[]{1,2,3};
}

a、b、arr 都是 func 方法内部的变量,存储在虚拟机栈的栈帧中。其中 a 和 b 是基本类型变量,直接存储值;arr 是数组引用变量,存储的是数组在堆中的首地址。

3.3引用变量的特性

引用变量存储的是对象在堆中的地址,因此多个引用变量可以指向同一个对象。当通过一个引用变量修改对象中的数据时,其他指向该对象的引用变量也能看到修改后的结果。

3.4null 的含义

null 在 Java 中表示 “空引用”,即一个不指向任何对象的引用。如果对 null 引用进行读写操作,会抛出NullPointerException异常。需要注意的是,Java 中 null 与 0 号地址的内存没有任何关联。

四、数组的应用场景

4.1保存数据

数组最基本的用途就是保存数据,我们可以将数据存储在数组中,然后通过遍历数组来使用这些数据。例如:

public static void main(String[] args) {
    int[] array = {1, 2, 3};
    for(int i = 0; i < array.length; ++i){
        System.out.println(array[i] + " ");
    }
}

4.2作为函数的参数

数组可以作为参数传递给函数,根据传递的类型不同,会有不同的表现:

  • 传递基本数据类型:当函数的参数是基本数据类型时,修改形参的值不会影响实参。例如:
public static void main(String[] args) {
    int num = 0;
    func(num);
    System.out.println("num = " + num);
}
public static void func(int x) {
    x = 10;
    System.out.println("x = " + x);
}
// 执行结果
// x = 10
// num = 0

  • 传递引用数据类型(数组):当函数的参数是数组时,修改数组中的元素会影响到函数外部的数组。这是因为数组是引用类型,传递的是数组在堆中的地址,函数内部和外部的引用指向同一个数组对象。

4.3作为函数的返回值

数组也可以作为函数的返回值,例如,我们可以编写一个函数来获取斐波那契数列的前 N 项,并将其以数组的形式返回:

public class TestArray {
    public static int[] fib(int n){
        if(n <= 0){
            return null;
        }
        int[] array = new int[n];
        array[0] = array[1] = 1;
        for(int i = 2; i < n; ++i){
            array[i] = array[i-1] + array[i-2];
        }
        return array;
    }
    public static void main(String[] args) {
        int[] array = fib(10);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}

五、二维数组

二维数组本质上是一个一维数组,只不过这个一维数组中的每个元素又都是一个一维数组。

5.1二维数组的定义

二维数组的基本语法为:数据类型[][] 数组名称 = new 数据类型[行数][列数] { 初始化数据 };。例如:

int[][] arr = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

5.2二维数组的遍历

我们可以通过嵌套循环来遍历二维数组,外层循环控制行数,内层循环控制列数。例如:

int[][] arr = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};
for (int row = 0; row < arr.length; row++) {
    for (int col = 0; col < arr[row].length; col++) {
        System.out.printf("%d\t", arr[row][col]);
    }
    System.out.println("");
}

同理,还存在三维数组、四维数组等更复杂的数组,但在实际开发中出现的频率较低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值