Java一维数组的定义和使用(非常详细)
在 Java 程序开发过程中,有时候需要存储大量的同类型数据。例如,存储一个班级 50 名学生的姓名,这时需要定义 50 个变量来保存姓名数据,但这种做法太烦琐了。那么,如何解决这类问题呢?
Java 语言提供了数组结构,它类似于一个容器,可以批量存储相同数据类型的元素。
一维数组的逻辑结构是线性表,它是最简单的数组。使用一维数组时,要先定义,然后做初始化,最后才能使用。本节为大家详细讲解一维数组的具体用法。
数组声明之后,就需要为数组对象分配一个固定长度的存储空间。在为数组对象分配内存空间时,需要使用 new 运算符。通过 new 运算符可以告诉编译器声明的数组存储什么类型的数据,以及数组要存储的元素个数。数组一旦创建长度就固定了,不能再次改变。
针对数组的声明和内存分配,举例说明如下:
第 2 行代码先通过 new 运算符创建了一个长度为 10 的整型数组空间,创建的数组空间是在 JVM 的堆内存中分配空间的。接着把数组对象赋值给 nums,也就是将数组对象的地址存储到了 nums 变量中。此时,nums 变量就指向了这个数据对象,因此通过 nums 可以访问到数组对象空间中的每一个元素。对于数组声明和数组对象内存分配,可以参考下图。

图 1 数组声明和内存分配
图 1(a)声明了一个整型数组变量 nums,这个变量对应一个栈内存的空间。因为 nums 没有指向数组对象,所以 nums 存储的内容是null。
图 1(b)中在堆内存中创建了一个连续的长度为 10 的整型数组对象空间,数组对象的首地址是 0x8A21。图 1(b)中声明的数组变量 nums 存储了数组对象的首地址,因此 nums 变量指向了这个数组对象,与这个数组对象有了引用关联。通过 nums 变量可以用下标索引的方式,访问数组中的每个元素。
另外,也可以使用一条语句完成数组的声明和内存分配,语法格式如下:
在 Java 中,数组对象被创建之后,数组中的元素都具有一个初始的默认值:
静态初始化语法如下:
第 2 种静态初始化的方式可以先声明数组变量,然后使用 new 运算符进行数组元素的初始化。另外,第 2 种方式中,右边表达式中的[ ]中不允许写数组长度,否则会发生语法错误。
静态初始化示例代码如下:
动态初始化的示例代码如下:
使用数组下标赋值的语法格式如下:
通过数组下标为元素赋值的代码示例如下:
接下来,通过案例来演示如何访问数组元素。
每个数组都有 length 属性,当通过 length 属性获取了数组长度之后,就可以通过循环的方式,使用下标逐一遍历数组中的每个元素。
接下来,使用 length 获取数组长度,并通过循环遍历数组元素。
foreach 循环的语法格式如下:
接下来,通过案例来演示 foreach 循环遍历数组。
注意,foreach 循环代码简洁,编写方便,但是有其局限性,当使用 foreach 循环遍历数组时,只能访问其中的元素,不能对元素进行修改。
接下来,通过案例进一步演示在使用 foreach 循环遍历数组的过程中,对元素进行修改会有什么结果。
所以,foreach 循环遍历数组的过程中无法修改所遍历的数据。因此,foreach并不能替代for循环,仅仅是让遍历的方法变得更简洁。
基本类型数组的特点是,数组元素的值是直接存储在数组元素中的。所以,定义基本类型数组并初始化时,会先为数组分配内存空间,然后将数据直接存入对应的数组元素中。
基本类型数组的初始化示例如下图所示。

图 2 值类型数组的初始化和设值
图 2(a)定义了一个值类型数组,也就是整型数组 nums。该数组长度为 5,初始化后每个数组元素的值都是 0。图 2(b)是为 nums 数组中的元素都设置一个整数值。从图 2 中可以看出,值类型数组的数据都是直接存储在数组元素中的。
接下来,通过案例来演示值类型数组的初始化和设值。
下面通过定义一个 Student 类型的数组来演示引用类型数组的使用。
为了便于大家更好地理解引用类型数组存储数据的特点,下面通过一个图例对引用类型数组的使用进行说明,如下图所示。

图 3 引用类型数组的数据存储方式
图 3(a)是引用类型数组定义并初始化的情况,引用类型数组的元素默认值都为 null,不指向任何数据。图 3(b)中,定义了学生类型的数组,数组长度为 2,数组包含两个元素。每个数组元素都存储了一个地址,分别指向不同的学生对象。
Java 语言提供了数组结构,它类似于一个容器,可以批量存储相同数据类型的元素。
一维数组的逻辑结构是线性表,它是最简单的数组。使用一维数组时,要先定义,然后做初始化,最后才能使用。本节为大家详细讲解一维数组的具体用法。
Java一维数组的定义
在 Java 中创建一个数组,需要 3 个步骤:声明数组、为数组对象分配内存空间、为数组元素赋值。其中,声明数组和为数组对象分配内存空间的语法如下:数据类型[] 数组名; // 声明一维数组,这种是推荐的写法 数据类型 数组名[]; // 声明一维数组的第二种写法 数组名 = new 数据类型[数组元素个数]; // 为数组对象分配内存空间
- 数据类型可以是 Java 语言中的任意数据类型,包括简单的基本数据类型和引用类型;
- 数组名是用来访问数组的标识,作用与变量名类似,在程序中可以通过数组名访问数组中的元素,数组名的命名规则与变量的命名规则相同;
-
[ ]
是定义数组类型的符号,声明数组时必须要有这个符号,这个符号可以放在数据类型后面,也可以放在数组名后面。
数组声明之后,就需要为数组对象分配一个固定长度的存储空间。在为数组对象分配内存空间时,需要使用 new 运算符。通过 new 运算符可以告诉编译器声明的数组存储什么类型的数据,以及数组要存储的元素个数。数组一旦创建长度就固定了,不能再次改变。
针对数组的声明和内存分配,举例说明如下:
int[] nums; // 声明数组名为nums的整型数组 nums = new int[10]; // 为nums数组分配存储10个整数的内存空间第 1 行代码只是声明了一个整数类型的数组变量 nums,但是这个变量没有指向任何一个数组对象空间,声明的数组变量在 JVM 的栈内存中分配空间。
第 2 行代码先通过 new 运算符创建了一个长度为 10 的整型数组空间,创建的数组空间是在 JVM 的堆内存中分配空间的。接着把数组对象赋值给 nums,也就是将数组对象的地址存储到了 nums 变量中。此时,nums 变量就指向了这个数据对象,因此通过 nums 可以访问到数组对象空间中的每一个元素。对于数组声明和数组对象内存分配,可以参考下图。

图 1 数组声明和内存分配
图 1(a)声明了一个整型数组变量 nums,这个变量对应一个栈内存的空间。因为 nums 没有指向数组对象,所以 nums 存储的内容是null。
图 1(b)中在堆内存中创建了一个连续的长度为 10 的整型数组对象空间,数组对象的首地址是 0x8A21。图 1(b)中声明的数组变量 nums 存储了数组对象的首地址,因此 nums 变量指向了这个数组对象,与这个数组对象有了引用关联。通过 nums 变量可以用下标索引的方式,访问数组中的每个元素。
另外,也可以使用一条语句完成数组的声明和内存分配,语法格式如下:
数据类型[] 数组名 = new 数据类型[数组元素个数]使用这种方式会在定义数组的同时为数组分配内存空间,举例说明如下:
int[] nums = new int[10]; // 声明数组的同时为数组分配内存空间在这行代码中,等号左边的 nums 是声明的数组变量,它指向了右边使用 new 运算符创建的数组对象。
在 Java 中,数组对象被创建之后,数组中的元素都具有一个初始的默认值:
- 整型数组的元素默认值是 0;
- 浮点类型数组的元素默认值是 0.0;
- 布尔类型数组的元素默认值是 false;
- 字符串和对象等引用类型数组的元素默认值都是 null。
数组元素的分配
在创建数组对象之后,就可以存储数据到数组元素空间中,进行数组元素的分配,也就是为数组元素赋值。为数组元素赋值的方式有3种:静态初始化、动态初始化、通过数组下标为数组赋值。1) 静态初始化
静态初始化就是在声明数组时,由开发者显式指定每个数组元素的初始值,初始值的类型要和定义数组的类型一致。根据这些初始值,系统会自动创建对应长度的数组空间,用于存储每个数组元素的数据。静态初始化语法如下:
数据类型[] 数组名 = {数据1,数据2,数据3,…,数据n}; // 静态初始化,第1种方式 数据类型[] 数组名; 数组名 = new 数据类型[]{数据1,数据2,数据3,…,数据n}; // 静态初始化,第2种方式第 1 种静态初始化的方式,需要在声明数组的同时进行数据初始化,初始化的数据要写在大括号中,并以逗号分隔。
第 2 种静态初始化的方式可以先声明数组变量,然后使用 new 运算符进行数组元素的初始化。另外,第 2 种方式中,右边表达式中的[ ]中不允许写数组长度,否则会发生语法错误。
静态初始化示例代码如下:
int[] nums = {10,20,30,40,50}; // 声明数组并进行静态初始化 String[] names; // 声明数组变量 names = new String[]{"唐僧","孙悟空","猪八戒","沙和尚"}; // 进行静态初始化
2) 动态初始化
进行数组动态初始化时,开发者只需要指定数组长度,然后由系统自动为数组元素分配初始值。动态初始化的语法格式如下:数据类型[] 数组名 = new 数据类型[数组长度];在进行动态初始化后,程序会根据指定的数组长度,创建对应长度的数组元素空间,并为每个数组元素空间设置初始值。
动态初始化的示例代码如下:
int[] nums = new int[5]; // 创建长度为5的整型数组,数组元素的初始值都是0 String[] names = new String[3]; // 创建长度为3的字符串数组,数组元素的初始值都为null
3) 通过数组下标为数组赋值
在数组创建之后,可以使用数组名结合数组下标的方式,为数组空间中的每个元素赋值。使用数组下标赋值的语法格式如下:
数据类型[] 数组名 = new 数据类型[数组长度]; 数组名[下标1] = 数值1; 数组名[下标2] = 数值2; … 数组名[数组长度-1] = 数值n;在通过数组下标为数组元素赋值时,数组下标的取值范围从 0 到数组长度减 1 为止。下标超出这个范围,会发生“ArrayIndexOutOfBoundsException”数组下标越界的异常。
通过数组下标为元素赋值的代码示例如下:
String[] names = new String[4]; // 声明长度为4的字符串数组 names[0] = "唐僧"; // 通过下标为每个数组元素赋值 names[1] = "孙悟空"; names[2] = "猪八戒"; names[3] = "沙和尚";
数组元素的访问
数组创建之后,最常用的操作就是访问数组元素,这包含为数组元素赋值和输出数组元素中的值。访问数组元素的方式是通过数组名结合数组下标的方式完成的。接下来,通过案例来演示如何访问数组元素。
public class Demo { public static void main(String[] args) { int[] nums = new int[3]; // 定义长度为3的整型数组 nums[0] = 10; // 为数组元素赋值 nums[1] = 20; nums[2] = 30; System.out.println(nums[0]); // 输出数组元素中的值 System.out.println(nums[1]); System.out.println(nums[2]); } }程序的运行结果如下:
10
20
30
length获取数组的长度
要获取数组的长度,可以通过数组对象的 length 属性。每个数组都有 length 属性,当通过 length 属性获取了数组长度之后,就可以通过循环的方式,使用下标逐一遍历数组中的每个元素。
接下来,使用 length 获取数组长度,并通过循环遍历数组元素。
public class Demo { public static void main(String[] args) { // 创建长度为3的数组对象 int[] nums = new int[3]; nums[0] = 10; // 为数组元素赋值 nums[1] = 20; nums[2] = 30; for (int i = 0; i < nums.length; i++) { // 使用length获取数组长度,作为循环条件 System.out.println(nums[i]); // 循环输出每个元素 } } }程序的运行结果如下:
10
20
30
使用foreach遍历数组
除了使用 for 循环遍历数组外,Java 中还有另外一种更简洁的遍历方法:foreach 循环遍历。这种方式也称为增强 for 循环,它的功能比较强大,遍历时不需要依赖数组的长度和下标,即可实现数组遍历。foreach 循环的语法格式如下:
for (数组中元素的类型 临时变量 : 数组对象变量) { 程序语句; }通过上面的语法结构可以看出,foreach 循环遍历数组时不需要获取数组长度,也不需要用索引去访问数组中的元素,这是与 for 循环不同的地方。foreach 循环会自动将数组中的元素逐一取出,存入一个临时变量中,然后使用临时变量进行数据处理,从而完成数组元素的遍历。
接下来,通过案例来演示 foreach 循环遍历数组。
public class Demo { public static void main(String[] args) { String[] names = {"唐僧", "孙悟空", "猪八戒", "沙和尚"}; // 声明数组并进行初始化 for (String name : names) { // 使用foreach循环逐一取出数组元素并存入临时变量 System.out.println(name); // 输出临时变量存储的数据 } } }程序的运行结果如下:
唐僧
孙悟空
猪八戒
沙和尚
注意,foreach 循环代码简洁,编写方便,但是有其局限性,当使用 foreach 循环遍历数组时,只能访问其中的元素,不能对元素进行修改。
接下来,通过案例进一步演示在使用 foreach 循环遍历数组的过程中,对元素进行修改会有什么结果。
public class Demo { public static void main(String[] args) { String[] strs = new String[3]; // 创建一个长度为3的数组 int i = 0; for (String str : strs) { // 循环遍历数组 str = new String("字符串:" + i); // 修改每个遍历到的值 i++; } for (String str : strs) { // 打印数组中的值 System.out.println(str); } } }程序的运行结果如下:
null
null
null
所以,foreach 循环遍历数组的过程中无法修改所遍历的数据。因此,foreach并不能替代for循环,仅仅是让遍历的方法变得更简洁。
基本类型数组的初始化
按照数据类型的不同,数组可分为基本类型数组和引用类型数组。基本类型数组的特点是,数组元素的值是直接存储在数组元素中的。所以,定义基本类型数组并初始化时,会先为数组分配内存空间,然后将数据直接存入对应的数组元素中。
基本类型数组的初始化示例如下图所示。

图 2 值类型数组的初始化和设值
图 2(a)定义了一个值类型数组,也就是整型数组 nums。该数组长度为 5,初始化后每个数组元素的值都是 0。图 2(b)是为 nums 数组中的元素都设置一个整数值。从图 2 中可以看出,值类型数组的数据都是直接存储在数组元素中的。
接下来,通过案例来演示值类型数组的初始化和设值。
public class Demo { public static void main(String[] args) { int[] nums = new int[5]; // 定义长度为5的数组,并动态初始化 for (int n : nums) { // 使用foreach输出每个元素值 System.out.println(n); } System.out.println("=========="); // 输出分隔符 nums[0] = 34; nums[1] = 21; nums[2] = 15; nums[3] = 56; nums[4] = 71; // 为每个数组元素设置特定值 for (int i = 0; i < nums.length; i++) { // 使用for循环输出每个元素 System.out.println(nums[i]); } } }程序的运行结果如下:
0
0
0
0
0
==========
34
21
15
56
71
引用类型数组的初始化
引用类型数组中存储的是数据的引用地址。通过引用地址指向了实际存储数据的内存区域。下面通过定义一个 Student 类型的数组来演示引用类型数组的使用。
class Student { // 学生类 String name; // 姓名 int age; // 年龄 } public class Demo { public static void main(String[] args) { Student[] stus = new Student[2]; // 创建长度为2的学生数组 stus[0] = new Student(); // 为第1个数组元素存储学生对象 stus[0].name = "张三"; // 设置学生对象的属性 stus[0].age = 20; stus[1] = new Student(); // 为第2个数组元素存储学生对象 stus[1].name = "李四"; // 设置学生对象的属性 stus[1].age = 18; for (Student s : stus) { // 使用foreach循环输出学生对象数据 System.out.println(s.name + " " + s.age); } } }程序的运行结果如下:
张三 20
李四 18
为了便于大家更好地理解引用类型数组存储数据的特点,下面通过一个图例对引用类型数组的使用进行说明,如下图所示。

图 3 引用类型数组的数据存储方式
图 3(a)是引用类型数组定义并初始化的情况,引用类型数组的元素默认值都为 null,不指向任何数据。图 3(b)中,定义了学生类型的数组,数组长度为 2,数组包含两个元素。每个数组元素都存储了一个地址,分别指向不同的学生对象。