在之前的编程学习中,我们主要使用单个变量来存储数据。每个变量只能存储一个值,比如一个整数、一个浮点数或一个字符串。但是,在实际编程中,我们经常需要处理大量的相关数据。
如果你要管理一个班级的学生成绩,你需要存储每个学生的分数。如果班级有30个学生,你就需要30个变量来存储这些成绩。这样做不仅繁琐,而且难以管理。 这就是数组发挥作用的地方。数组是一种可以同时存储多个相同类型值的对象。它就像一个容器,可以容纳多个相关的数据项。

在Java中,创建和使用数组类似于创建和使用其他类型的对象:你声明一个引用变量,然后使用new关键字在内存中创建数组实例。
让我们看一个例子:
|int[] numbers;
这个语句声明了一个名为numbers的数组引用变量。这个变量可以引用一个int值数组。注意这个语句看起来像一个普通的int变量声明,只是在int后面有一对方括号。方括号表示这个变量是对int数组的引用。
声明数组引用变量并不会创建数组。下一步是使用new关键字创建数组并将其地址赋给numbers变量:
|numbers = new int[6];
方括号内的数字是数组的大小声明符。它表示数组可以容纳的元素数量。当这个语句执行时,numbers将引用一个可以容纳6个int元素的数组。
与其他类型的对象一样,在Java中你可以通过一条语句同时完成数组引用变量的声明和数组实例的创建。这样不仅让代码更加简洁,也减少了出错的可能。 例如,下面的语句同时声明了一个int类型的数组引用变量numbers,并创建了一个可以存储6个整数的数组对象。这样,numbers变量就可以直接用来访问和操作这个数组中的元素。
|int[] numbers = new int[6];
可以声明任何数据类型的数组。以下都是有效的数组声明:
|float[] temperatures = new float[100]; char[] letters = new char[41]; long[] units = new long[50]; double[] sizes = new double[1200];
在Java中,数组的大小声明符(即方括号中的数字)必须是一个非负整数表达式。这个表达式可以是一个直接写出来的数字(字面值),比如6,也可以是一个变量,甚至是一个能计算出整数结果的表达式。需要注意的是,数组的大小一旦确定,在整个数组生命周期内是不能改变的。
在实际开发中,为了让代码更易于维护和理解,通常会使用final关键字声明一个常量变量来表示数组的大小。这样做有几个好处:
final修饰的变量值不能被修改,避免了程序运行过程中被意外更改。例如,下面的代码中,NUM_ELEMENTS就是一个用final修饰的常量,被用作数组的大小声明符:
|final int NUM_ELEMENTS = 6; int[] numbers = new int[NUM_ELEMENTS];
这种做法可以使程序更容易维护。当我们将数组的大小存储在变量中时,我们可以在引用数组大小时使用变量而不是字面数字。如果我们需要改变数组的大小,只需要改变变量的值即可。

虽然数组本身只有一个名称,但它实际上是由一组有序的元素组成的。每个元素在数组中都有一个唯一的位置,这个位置由一个称为“下标”或“索引”(index)的数字来标识。
下标从0开始递增,也就是说,第一个元素的下标是0,第二个元素的下标是1,依此类推。通过数组名和下标的组合(例如:numbers[0]),我们可以像访问普通变量一样,单独访问和操作数组中的每一个元素。 下标的存在,使得我们能够灵活地读取、修改或处理数组中的任意元素,而不仅仅是整体操作整个数组。
numbers数组中的每个元素,当通过其下标访问时,都可以用作int变量。例如,看以下代码:
|numbers[0] = 20; numbers[3] = 30;
第一个语句将20存储在数组的第一个元素(元素0)中,第二个语句将30存储在第四个元素(元素3)中。
下面详细带你了解如何从键盘读取值并将它们存储到数组元素中。实际上,操作数组元素和操作普通变量类似。你可以通过下标访问数组的每一个元素,将输入的值赋给它们。同时,也可以使用print和println方法来输出数组中各个元素的内容,实现对数组数据的读取和展示。
让我们看一个例子:
|import java.util.Scanner; public class ArrayDemo1 { public static void main(String[] args) { final int EMPLOYEES = 3; // 员工数量 int[] hours = new int[EMPLOYEES]; // 小时数组 // 创建Scanner对象用于键盘输入 Scanner keyboard = new Scanner(System.in); System.out.
运行这个程序会输出:
|请输入3个员工的工作小时数。 员工1:40 员工2:20 员工3:15 你输入的小时数是: 40 20 15
详细带你了解:下标数字其实可以存储在变量中,这样我们就能利用循环来“遍历”整个数组,对每个元素执行相同的操作。比如,上面的程序就可以通过两个for循环来实现更简洁的写法:
|import java.util.Scanner; public class ArrayDemo2 { public static void main(String[] args) { final int EMPLOYEES = 3; // 员工数量 int[] hours = new int[EMPLOYEES]; // 小时数组 // 创建Scanner对象用于键盘输入 Scanner keyboard = new Scanner(System.in); System.out.
运行这个程序会输出:
|请输入3个员工的工作小时数。 员工1:40 员工2:20 员工3:15 你输入的小时数是: 40 20 15
在Java中,数组具有严格的边界检查机制。也就是说,Java会在程序运行时自动检测你访问数组元素时所使用的下标是否在合法范围内。如果你尝试访问小于0或者大于等于数组长度的下标,Java会抛出异常并终止程序运行,从而防止数据越界带来的错误和安全隐患。
举个例子,假设我们创建了一个包含10个元素的数组:
数组的下标是从0开始的,所以这个数组的有效下标范围是0到9(共10个位置)。任何试图访问下标为-1或10及以上的位置,都会被Java检测到并报错。
|int[] values = new int[10];
Java不允许语句使用小于0或大于9的下标。
在Java中,数组的边界检查是在程序运行时动态进行的,而不是在编译阶段完成的。这意味着,如果你在代码中写下了一个使用非法下标(比如负数或超出数组长度的下标)访问数组元素的语句
,Java编译器并不会在编译时报告错误。只有当程序实际运行到这条语句时,Java才会检测到下标越界的情况。一旦发现下标不合法,Java会立即抛出一个ArrayIndexOutOfBoundsException异常,并终止程序的执行。
这种机制可以有效防止由于数组越界导致的数据错误或安全隐患,但也要求开发者在编写代码时格外注意数组下标的合法性。
让我们看一个例子:
|public class InvalidSubscript { public static void main(String[] args) { int[] values = new int[3]; System.out.println("我将尝试在三个元素的数组中存储四个数字。"); for (int index = 0; index < 4; index++) { System.out.
运行这个程序会输出:
|我将尝试在三个元素的数组中存储四个数字。 现在处理元素0 现在处理元素1 现在处理元素2 现在处理元素3 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at InvalidSubscript.main(InvalidSubscript.java:17)
由于Java数组的下标是从0开始的,而不是从1开始,这很容易导致所谓的“差一错误”(off-by-one error)。差一错误通常发生在循环处理数组时,循环的起始值或终止条件设置不当, 导致数组的第一个元素(下标0)被遗漏,或者尝试访问不存在的下标(如等于数组长度的下标),从而引发异常。请看下面的示例代码:
|// 这段代码有差一错误 final int SIZE = 100; int[] numbers = new int[SIZE]; for (int index = 1; index <= SIZE; index++) { numbers[index] = 0; }
这段代码的意图是创建一个包含100个整数的数组,并在每个元素中存储值0。但是,这段代码有差一错误。 循环使用其控制变量index作为numbers数组的下标。在循环执行期间,变量index取值为1到100,而它应该取值为0到99。 结果,第一个元素(位于下标0)被跳过。此外,循环在最后一次迭代中尝试使用100作为下标。因为100是无效的下标,程序将抛出异常并停止。
在Java中,数组的初始化可以像普通变量一样在声明时直接进行。也就是说,你可以在创建数组的同时,为数组的每个元素赋予初始值,这样无需再逐个为元素赋值。下面是一个具体的例子,演示了如何在声明数组时使用初始化列表为数组元素赋初值:
|int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
这个语句声明引用变量days,在内存中创建一个数组,并在数组中存储初始值。大括号内用逗号分隔的值系列称为初始化列表。这些值按照它们在列表中出现的顺序存储在数组元素中。
注意,当你使用初始化列表时,不使用new关键字。Java自动创建数组并在其中存储初始化列表中的值。
让我们看一个完整的例子:
|public class ArrayInitialization { public static void main(String[] args) { int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
运行这个程序会输出:
|第1个月有31天。 第2个月有28天。 第3个月有31天。 第4个月有30天。 第5个月有31天。 第6个月有30天。 第7个月有31天。 第8个月有31天。 第9个月有30天。 第10个月有31天。 第11个月有30天。 第12个月有31天。
在Java中,访问和操作数组元素的方式与普通变量非常相似。你可以通过数组名和下标来读取或修改数组中的某个元素。 例如,假设有一个名为hours的整型数组和一个名为payRate的变量,下面的语句会取出hours数组中下标为3的元素(即第4个元素),并将其与payRate相乘,结果赋值给grossPay变量:
|grossPay = hours[3] * payRate;
以下是数组元素上预增量和后增量操作的示例:
|int[] score = {7, 8, 9, 10, 11}; ++score[2]; // 预增量操作 score[4]++; // 后增量操作
让我们看一个在简单数学语句中使用数组元素的例子:
|import java.util.Scanner; public class PayArray { public static void main(String[] args) { final int EMPLOYEES = 5; // 员工数量 double payRate; // 小时工资率 double grossPay; // 总工资 // 创建数组来保存员工小时数 int[] hours = new int[EMPLOYEES]; // 创建Scanner对象用于键盘输入
运行这个程序会输出:
|请输入5个员工的工作小时数,他们都赚取相同的小时工资率。 员工#1:10 员工#2:20 员工#3:30 员工#4:40 员工#5:50 请输入每个员工的小时工资率:10 以下是每个员工的总工资: 员工#1:$100.0 员工#2:$200.0 员工#3:$300.0 员工#4:$400.0 员工#5:$500.0
详细带你了解数组元素在关系表达式中的用法。例如,下面的if语句判断cost[20]是否小于cost[0]:
|if (cost[20] < cost[0]) { // 执行某些操作 }
以下while循环在value[count]不等于0时迭代:
|while (value[count] != 0) { // 语句 }
在Java中,每个数组对象都自带一个名为length的公共实例字段。这个length字段用于存储该数组实际包含的元素数量。无论数组的数据类型如何(如int[]、double[]、String[]等),都可以通过数组名.length的方式获取数组的长度。需要注意的是,length是一个字段(属性),不是方法,因此在访问时不需要加括号。例如,假设我们通过如下语句创建了一个数组:
|double[] temperatures = new double[25];
因为temperatures数组有25个元素,以下语句会将25赋给变量size:
|size = temperatures.length;
length字段在处理数组的全部内容时很有用。例如,以下循环遍历数组并显示每个元素的内容。数组的length字段在测试表达式中用作循环控制变量的上限:
|for (int i = 0; i < temperatures.length; i++) { System.out.println(temperatures[i]); }
注意:使用length字段作为下标的上限时要小心不要造成差一错误。length字段包含数组中元素的数量。数组中最大的下标是length - 1。
Java提供了一个专门的for循环版本,在许多情况下简化了数组处理。它被称为增强for循环。以下是增强for循环的一般格式:
|for (dataType elementVariable : array) { statement; }
让我们更仔细地看看语法:
dataType elementVariable:这是一个变量声明。这个变量在每次循环迭代期间将接收不同数组元素的值。在第一次循环迭代期间,它接收第一个元素的值;在第二次迭代期间,它接收第二个元素的值,依此类推。这个变量必须与数组元素具有相同的数据类型,或者是元素可以自动转换的类型。
array:你希望循环操作的数组的名称。循环将为数组中的每个元素迭代一次。
statement:在循环迭代期间执行的语句。
例如,假设我们有以下数组声明:
|int[] numbers = {3, 6, 9};
我们可以使用以下增强for循环来显示numbers数组的内容:
|for (int val : numbers) { System.out.println(val); }
因为numbers数组有三个元素,这个循环将迭代三次。第一次迭代时,val变量将接收numbers[0]中的值。在第二次迭代期间,val将接收numbers[1]中的值。在第三次迭代期间,val将接收numbers[2]中的值。代码的输出如下:
|3 6 9
当你需要访问存储在数组中的值时,从第一个元素到最后一个元素,增强for循环比传统for循环更简单。使用增强for循环,你不必担心数组的大小,也不必创建"索引"变量来保存下标。
但是,在某些情况下增强for循环是不够的。你不能在以下情况下使用增强for循环:
在任何这些情况下,你都应该使用传统for循环来处理数组。
在Java中,声明数组时,数组的大小(即元素的个数)可以由一个整数变量动态指定,而不仅仅是一个固定的常量。 这意味着你可以在程序运行时,根据用户的输入来决定数组的长度,从而实现灵活的数据存储。例如,你可以先询问用户需要存储多少个数据项,然后根据用户输入的数量来创建相应大小的数组。 这样,程序就能够适应不同的需求和场景。下面我们通过一个具体的例子来演示如何让用户输入数组的大小,并据此创建数组:
|import java.util.Scanner; public class DisplayTestScores { public static void main(String[] args) { int numTests; // 测试数量 int[] tests; // 测试分数数组 // 创建Scanner对象用于键盘输入 Scanner keyboard = new Scanner(System.in); // 获取测试分数数量 System.out.print("你有多少个测试?"); numTests =
运行这个程序会输出:
|你有多少个测试?5 输入测试分数1:72 输入测试分数2:85 输入测试分数3:81 输入测试分数4:94 输入测试分数5:99 以下是你输入的分数: 72 85 81 94 99
详细带你了解:在开发涉及数组的应用程序时,我们经常需要编写能够接收数组作为参数的方法。当你将数组作为参数传递给方法时, 实际上传递的是该数组的内存地址(引用)。因此,方法内部的参数变量会引用同一个数组,这样方法就可以直接访问和操作原始数组的数据。
当数组的单个元素传递给方法时,它像任何其他变量一样处理。例如,以下循环将数组numbers的每个元素传递给方法showValue:
|public class PassElements { public static void main(String[] args) { int[] numbers = {5, 10, 15, 20, 25, 30, 35, 40}; for (int index = 0; index < numbers.length; index
运行这个程序会输出:
|5 10 15 20 25 30 35 40
详细带你了解:如果你希望方法能够接收整个数组作为参数,方法的参数类型就需要声明为数组类型。 例如,下面的方法定义中,参数 array 被声明为 int 数组的引用变量,这意味着该参数可以接收一个完整的数组,而不仅仅是单个元素:
|public static void showArray(int[] array) { for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } }
当你将数组作为参数传递时,你只需传递引用数组的变量中的值,如下所示:
|showArray(numbers);
当你将整个数组作为参数传递给方法时,实际上并不是把数组中的所有元素逐个复制到方法内部,而是把这个数组在内存中的“地址”(也就是引用)传递给方法的参数变量。 这样,方法内部的参数变量和原始数组变量都指向同一个数组对象。换句话说,方法内部对数组元素的任何修改,都会直接影响到原始数组,因为它们操作的是同一块内存空间。 这种机制和对象作为参数传递时的行为是一样的。因此,数组作为参数传递时,方法可以直接读取和修改原始数组的内容,而不仅仅是获得一份副本。
让我们看一个完整的例子:
|import java.util.Scanner; public class PassArray { public static void main(String[] args) { final int ARRAY_SIZE = 4; // 数组大小 // 创建数组 int[] numbers = new int[ARRAY_SIZE]; // 将数组传递给getValues方法 getValues(numbers); System.out.println
运行这个程序会输出:
|输入4个数字的系列。 输入数字1:2 输入数字2:4 输入数字3:6 输入数字4:8 以下是你输入的数字: 2 4 6 8
在上一部分中,你看到不能通过简单地将一个数组的引用变量赋给另一个数组的引用变量来复制数组。此外,你不能使用==操作符来比较两个数组引用变量并确定数组是否相等。
例如,以下代码看起来比较两个数组,但实际上没有:
|int[] firstArray = {5, 10, 15, 20, 25}; int[] secondArray = {5, 10, 15, 20, 25}; if (firstArray == secondArray) { // 这是一个错误 System.out.println("数组相同。"); } else { System.out.
当你使用==操作符与引用变量(包括引用数组的变量)时,操作符比较变量包含的内存地址,而不是变量引用的对象的内容。 因为这段代码中的两个数组变量引用内存中的不同对象,它们将包含不同的地址。因此,布尔表达式firstArray == secondArray的结果为false,代码报告数组不同。
要比较两个数组的内容,你必须比较两个数组的元素。例如,看以下代码:
|int[] firstArray = {2, 4, 6, 8, 10}; int[] secondArray = {2, 4, 6, 8, 10}; boolean arraysEqual = true; // 标志变量 int index = 0; // 循环控制变量 // 首先确定数组是否相同大小 if
要对数组中的值求和,你必须使用带有累加器变量的循环。循环将每个数组元素的值添加到累加器中。例如,假设以下语句出现在程序中,并且值已存储在units数组中:
|int[] units = new int[25];
以下循环将units数组的每个元素的值添加到total变量中。当代码完成时,total将包含units数组所有元素的总和:
|int total = 0; // 初始化累加器 for (int index = 0; index < units.length; index++) { total += units[index]; }
计算数组中所有值平均值的第一个步骤是对值求和。第二个步骤是将总和除以数组中元素的数量。假设以下语句出现在程序中,并且值已存储在scores数组中:
|double[] scores = new double[10];
以下代码计算scores数组中值的平均值。当代码完成时,平均值将存储在average变量中:
|double total = 0; // 初始化累加器 double average; // 将保存平均值 for (int index = 0; index < scores.length; index++) { total += scores[index]; } average = total / scores.length;
注意,将total除以scores.length的最后一条语句不在循环内。这条语句应该只在循环完成其迭代后执行一次。
在数组中找到最高和最低值的算法非常相似。首先,让我们看看在数组中找到最高值的代码。假设以下语句存在于程序中,并且值已存储在numbers数组中:
|int[] numbers = new int[50];
在数组中找到最高值的代码如下:
|int highest = numbers[0]; for (int index = 1; index < numbers.length; index++) { if (numbers[index] > highest) { highest = numbers[index]; } }
首先,我们将第一个数组元素的值复制到变量highest中。然后循环将数组中所有剩余的数组元素(从下标1开始)与highest中的值进行比较。每次它在数组中找到大于highest的值时,它将该值复制到highest中。当循环完成时,highest将包含数组中的最高值。
以下代码在数组中找到最低值。如你所见,它几乎与找到最高值的代码相同:
|int lowest = numbers[0]; for (int index = 1; index < numbers.length; index++) { if (numbers[index] < lowest) { lowest = numbers[index]; } }
当循环完成时,lowest将包含数组中的最低值。
在Java中,方法不仅可以接收数组作为参数,还可以将数组作为返回值返回。这意味着方法能够创建一个数组、填充数据后,将该数组的引用返回给调用者。要实现这一点,必须在方法的声明中正确指定返回类型为相应的数组类型(例如int[]、double[]等)。这样,调用该方法时,就可以获得一个新的数组引用,并在主程序中使用这个数组。需要注意的是,方法实际返回的是数组对象的引用,而不是数组的所有元素的副本,这样可以高效地在不同方法之间传递和操作数组数据。
例如,看以下方法定义:
|public static double[] getArray() { double[] array = {1.2, 2.3, 4.5, 6.7, 8.9}; return array; }
getArray方法返回一个double数组。注意方法头中列出的返回类型是double[]。这表示方法返回对double数组的引用。
让我们看一个完整的例子:
|public class ReturnArray { public static void main(String[] args) { double[] values; values = getArray(); for (double num : values) { System.out.print(num + " "); } } /** * getArray方法 *
运行这个程序会输出:
|1.2 2.3 4.5 6.7 8.9
在Java中,除了可以创建基本数据类型的数组外,还可以创建由String对象组成的数组。String数组实际上是一个对象引用数组,每个元素都可以存放一个String对象的引用。你可以在声明数组的同时进行初始化,也可以先声明数组再为每个元素赋值。下面是一个同时创建并初始化String对象数组的示例语句:
|String[] names = {"Bill", "Susan", "Steven", "Jean"};
在内存中,String对象数组的排列方式与基本数据类型的数组不同。为了使用String对象,你必须有一个对String对象的引用。因此,String对象数组实际上是对String对象的引用数组。
让我们看一个完整的例子:
|public class MonthDays { public static void main(String[] args) { String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
运行这个程序会输出:
|January has 31 days. February has 28 days. March has 31 days. April has 30 days. May has 31 days. June has 30 days. July has 31 days. August has 31 days. September has 30 days. October has 31 days. November has 30 days. December has 30 days.
回忆我们之前学过的String类,String对象有几种方法。例如,toUpperCase方法返回String对象的大写等效项。因为String数组的每个元素都是String对象,你可以使用元素调用String方法。
例如,以下语句使用names数组的元素0调用toUpperCase方法:
|System.out.println(names[0].toUpperCase());
以下代码显示了另一个例子。它使用names数组的元素3调用charAt方法。当这段代码执行时,存储在names[3]中的字符串的第一个字符将被赋给letter变量:
|// 声明一个名为letter的char变量 char letter; // 将names[3]中的第一个字符赋给letter letter = names[3].charAt(0);
和其他数据类型一样,你也可以创建某个类的对象数组。对象数组的每个元素实际上是对该类对象的引用。举个例子,假设我们在第6章实现了一个BankAccount类。 如果你想用一个数组来存储某个人的所有银行账户信息,就可以声明一个BankAccount类型的数组。这样,数组中的每个元素都可以用来引用一个BankAccount对象,实现对多个账户的统一管理和操作。
以下代码声明了一个包含五个BankAccount对象的数组:
|final int NUM_ACCOUNTS = 5; BankAccount[] accounts = new BankAccount[NUM_ACCOUNTS];
引用数组的变量名为accounts。与String数组一样,这个数组中的每个元素都是一个引用变量。
需要注意的是,当你创建一个对象数组时,数组中的每个元素初始值都是null。null是Java中的一个特殊值,表示该元素当前没有引用任何对象。也 就是说,虽然你已经为数组分配了空间,但这些空间里只是存放了“空引用”,并没有实际的对象实例。如果你直接访问这些元素并尝试调用它们的方法,会抛出NullPointerException异常。
因此,在使用对象数组之前,必须为数组中的每个元素分配一个实际的对象。通常可以使用循环来依次为每个元素创建对象实例。例如,下面的代码演示了如何通过for循环为accounts数组的每个元素分配一个新的BankAccount对象:
|for (int index = 0; index < accounts.length; index++) { accounts[index] = new BankAccount(); }
在这段代码中,为每个对象调用无参构造函数。回忆BankAccount类有一个无参构造函数,它将0.0赋给balance字段。
要访问对象数组中的元素,可以像访问其他类型的数组一样,通过下标来获取具体的对象引用。每个数组元素实际上都是对一个对象的引用,因此可以直接通过下标调用该对象的方法。例如,假设我们有一个BankAccount类型的数组accounts,下面的代码演示了如何通过下标访问数组中的第三个元素(即accounts[2]),并分别调用它的setBalance方法设置余额,以及调用withdraw方法进行取款操作:
accounts[2].setBalance(2500.0); 这行代码将accounts数组中下标为2的BankAccount对象的余额设置为2500.0。accounts[2].withdraw(500.0); 这行代码则让同一个账户对象执行取款操作,取出500.0。需要注意的是,只有在该数组元素已经被正确初始化为一个有效的对象实例后,才能调用其方法。如果该元素仍为null,直接调用方法会导致NullPointerException异常。
|accounts[2].setBalance(2500.0); accounts[2].withdraw(500.0);
让我们看一个使用对象数组的完整程序:
|import java.util.Scanner; public class ObjectArray { public static void main(String[] args) { final int NUM_ACCOUNTS = 3; // 账户数量 // 创建可以引用BankAccount对象的数组 BankAccount[] accounts = new BankAccount[NUM_ACCOUNTS]; // 为数组创建对象 createAccounts(accounts); // 显示每个账户的余额
运行这个程序会输出:
|输入账户1的余额:2500.0 输入账户2的余额:5000.0 输入账户3的余额:1500.0 以下是每个账户的余额: 账户1:$2500.0 账户2:$5000.0 账户3:$1500.0
二维数组是数组的数组。它可以被认为有行和列。数组对于存储和处理一组数据很有用。但是,有时需要处理多组数据。例如,在成绩平均程序中,老师可能将所有一个学生的测试分数记录在double数组中。 如果老师有30个学生,这意味着她需要30个数组来记录整个班级的分数。但是,与其定义30个单独的数组,不如定义一个二维数组。
你到目前为止研究的数组是一维数组。它们被称为一维是因为它们只能保存一组数据。二维数组,有时称为2D数组,可以保存多组数据。虽然二维数组实际上是数组的数组,但最好将其视为具有行和列元素的数组。
要声明二维数组,需要两组方括号和两个大小声明符:第一个用于行数,第二个用于列数。以下是具有三行四列的二维数组声明的例子:
|double[][] scores = new double[3][4];
数据类型中的两组方括号表示scores变量将引用二维数组。数字3和4是大小声明符。第一个大小声明符指定行数,第二个大小声明符指定列数。
处理二维数组中的数据时,每个元素都有两个下标:一个用于其行,另一个用于其列。在scores数组中,第0行中的元素引用如下:
|scores[0][0] scores[0][1] scores[0][2] scores[0][3]
第1行中的元素如下:
|scores[1][0] scores[1][1] scores[1][2] scores[1][3]
第2行中的元素如下:
|scores[2][0] scores[2][1] scores[2][2] scores[2][3]
要访问二维数组中的元素之一,你必须使用两个下标。例如,以下语句将数字95存储在scores[2][1]中:
|scores[2][1] = 95;
处理二维数组的程序可以使用嵌套循环。例如,以下代码提示用户为数组中的每个元素输入分数:
|final int ROWS = 3; final int COLS = 4; double[][] scores = new double[ROWS][COLS]; for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { System.out.print
以下代码显示scores数组中的所有元素:
|for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { System.out.println(scores[row][col]); } }
让我们看一个使用二维数组存储公司销售数据的完整程序:
|import java.util.Scanner; public class CorpSales { public static void main(String[] args) { final int DIVS = 3; // 公司中的三个部门 final int QTRS = 4; // 四个季度 double totalSales = 0.0; // 累加器 // 创建数组来保存每个部门每个季度的销售 double[][] sales
运行这个程序会输出:
|这个程序将计算公司所有部门的总销售额。输入以下销售数据: 部门1,季度1:$35698.77 部门1,季度2:$36148.63 部门1,季度3:$31258.95 部门1,季度4:$30864.12 部门2,季度1:$41289.64 部门2,季度2:$43278.52 部门2,季度3:$40928.18 部门2,季度4:$42818.98 部门3,季度1:$28914.56 部门3,季度2:$27631.52 部门3,季度3:$30596.64 部门3,季度4:$29834.21 公司总销售额:$419,262.72
8. 数组创建和初始化练习
编写代码创建并初始化一个包含5个整数的数组,并打印所有元素。
|public class ArrayDemo { public static void main(String[] args) { // 方法1:先创建数组,再赋值 int[] numbers1 = new int[5]; numbers1[0] = 10; numbers1[1] = 20; numbers1[2] = 30;
9. 数组处理练习
编写一个程序,计算数组中所有元素的总和和平均值。
|public class ArraySumAverage { public static void main(String[] args) { // 创建并初始化数组 int[] numbers = {85, 90, 78, 92, 88}; // 计算总和 int sum = 0; for (int i =
10. 数组搜索练习
编写一个方法,在数组中搜索特定值并返回其位置(索引),如果找不到返回-1。
|public class ArraySearch { public static void main(String[] args) { int[] numbers = {10, 20, 30, 40, 50}; // 搜索不同的值 int index1 = search(numbers, 30); if (index1 != -1
11. 数组最大值和最小值练习
编写一个程序,找到数组中的最大值和最小值。
|public class ArrayMaxMin { public static void main(String[] args) { int[] numbers = {85, 90, 78, 92, 88, 95, 82}; // 找到最大值和最小值 int max = findMax(numbers); int min =
输出结果:
|方法1创建的数组: numbers1[0] = 10 numbers1[1] = 20 numbers1[2] = 30 numbers1[3] = 40 numbers1[4] = 50 ---------------- 方法2创建的数组: numbers2[0] = 10 numbers2[1] = 20 numbers2[2] = 30 numbers2[3] = 40 numbers2[4] = 50
说明:
new int[5]创建包含5个整数的数组数组名[索引]访问和赋值{值1, 值2, ...}直接初始化数组输出结果:
|数组元素: 85 90 78 92 88 总和: 433 平均值: 86.6
说明:
(double))数组名.length获取数组长度输出结果:
|找到30,位置在索引: 2 未找到25
说明:
输出结果:
|数组元素: 85 90 78 92 88 95 82 最大值: 95 最小值: 78
说明: