在Java中,数组的定义有三种方式,其基本语法格式如下:
数组类型[] 数组名 = new 数组类型[数组长度];
数组类型[] 数组名 = new 数组类型[]{数组元素0,数组元素1,...};
数组类型[] 数组名 = {数组元素0,数组元素1,...};
在上述三种定义数组的语法格式中,数组类型可以是前面小节中介绍的变量的数据类型,数组名就是定义的变量名。
要符合标识符的规范,数组长度表示该数组中可容纳的数组元素的个数,而数组元素0、数组元素1就表示定义的数组中具体包含的数据。
以上三种定义数组语法格式的实际使用示例如下:
int[] ids = new int[100];
String[] names = new String[]{"张三","tom",...};
Object[] object = {"张三","tom",...};
第一种方式定义了一个int[]数组类型的变量ids,使用new int[100]指定了该数组的长度(也就是元素的个数)为100,但并没有为数组中的元素赋值;
第二种和第三种方式分别定义了一个String[]类型和Object[]类型的数组变量names和object,并都通过“=”右边的大括号“{}”为数组完成了初始化赋值。
关于数组在内存中的存储方式,这里以上述定义数组的第一种方式为例,来进行具体说明。第一种数组定义的方式,相当于在内存中定义了100个int类型的变量,第一个变量的名称为ids[0],第二个变量的名称为ids[1]。
以此类推,第100个变量的名称为ids[99],这些变量的初始值都是0。为了更好地理解数组的这种定义方式,可以将上面的一句代码分成两句来写。
具体如下:
int[] ids; // 声明一个int[]类型的变量
ids = new int[100]; // 创建一个长度为100的数组,并将数组地址赋值给数组类型的变量x
接下来通过两张内存图来详细地说明数组在创建过程中内存的分配情况。
第一行代码 int[] ids; 声明了一个变量ids,该变量的类型为int[],即一个int类型的数组。变量ids会占用一块内存单元,它没有被分配初始值。此时ids在内存中的状态如图1所示。
第二行代码 ids = new int[100]; 创建了一个数组,并将数组的内存地址赋值给变量ids。在程序运行期间可以使用变量ids来引用数组,这时内存中的状态会发生变化,如图2所示。
图2描述了变量ids引用数组的情况。该数组中有100个元素,初始值都为0。数组中的每个元素都有一个索引(也可称为角标),要想访问数组中的元素可以通过“数组名[角标]”的形式,即“ids[0]、…、ids[99]”。
需要注意的是,数组中最小的索引是0,最大的索引是“数组的长度-1”。在Java中,为了方便获得数组的长度,提供了一个length属性,在程序中可以通过“数组名.length”的方式来获得数组的长度,即数组元素的个数。
接下来通过一个完整的案例来演示如何定义数组以及访问数组中的元素,如文件1所示。
文件1 Example18.java
public class Example18 {
public static void main(String[] args) {
// 1、第一种方式定义数组
int[] ids = new int[100];
System.out.println("ids[0]="+ids[0]); //访问数组第一个元素
System.out.println("ids[99]="+ids[99]);//访问数组最后一个元素
System.out.println("==============");
// 2、第二种方式定义数组
String[] names = new String[]{"张三","tom","jack"};
System.out.println("names[0]="+names[0]); //访问数组第一个元素
System.out.println("names[2]="+names[2]); //访问数组最后一个元素
System.out.println("==============");
// 3、第三种方式定义数组
Object[] object = {"张三","tom","jack"};
System.out.println("数组的长度为:"+object.length);//获取数组的长度
System.out.println("object[0]="+object[0]); //访问数组第一个元素
System.out.println("object[2]="+object[2]); //访问数组最后一个元素
}
}
运行结果如图3所示:
文件1中,分别声明了一个int[]类型、String[]类型和Object[]类型的数组,然后通过“数组名[角标]”的形式获取了数组的第一个和最后一个元素值,并打印到控制台上。从打印结果可以看出,第一种定义数组方式定义的int[]类型的数组中元素的初始值都为0。
这是因为当数组被成功创建后,数组中元素会被自动赋予一个默认值,根据元素类型的不同,默认初始化的值也是不一样的;而第二种和第三种定义数组方式定义的数组都指定了初始值,所以打印出对应角标的元素值。
Java中不同数据类型元素的初始值如下表所示:
在使用数组时,如果不想使用这些默认初始值,可以显式地为这些元素赋值,当然也可以对定义数组时的指定初始值进行修改。接下来对上面的案例进行修改来学习一下如何为数组中的元素赋值和修改,如文件2所示。
文件2 Example19.java
public class Example19 {
public static void main(String[] args) {
// 1、第一种方式定义数组
int[] ids = new int[100];
System.out.println("ids[0]="+ids[0]); //访问数组第一个元素
// 为数组指定元素进行初始化赋值
ids[0] = 2500;
System.out.println("ids[0]="+ids[0]); //再次访问数组第一个元素
System.out.println("==============");
// 2、第二种方式定义数组
String[] names = new String[]{"张三","tom","jack"};
System.out.println("names[0]="+names[0]); //访问数组第一个元素
// 为数组定义时指定的初始值进行修改
names[0] = "李四";
System.out.println("names[0]="+names[0]); //再次访问数组第一个元素
System.out.println("==============");
// 3、第三种方式定义数组
Object[] object = {"张三","tom","jack"};
System.out.println("object[0]="+object[0]); //访问数组第一个元素
// 为数组定义时指定的初始值进行修改
object[0] = "李四";
System.out.println("object[0]="+object[0]); //再次访问数组第一个元素
}
}
运行结果如图4所示:
文件2中,三种定义数组的方式都使用了“数组名[角标]=元素值”的形式对各数组中指定角标的元素进行了赋值和修改。
从修改的代码以及程序运行结果可以看出,对数组中的元素进行赋值或修改操作所使用的方式一样,只是在使用“数组名[角标]=元素值”的形式对数组元素进行操作时,如果数组指定角标的元素只有默认初始值,那么就是对元素进行的赋值操作;如果数组指定角标的元素已经有了初始值,那么就是对元素进行的修改操作。
注意:
1.每个数组的索引都有一个范围,即0~length-1。在访问数组的元素时,索引不能超出这个范围,否则程序会报错,如文件3所示。
文件3 Example20.java
public class Example20 {
public static void main(String[] args) {
int[] arr = new int[4]; // 定义一个长度为4的数组
System.out.println("arr[4]=" + arr[4]); // 通过角标4访问数组元素
}
}
运行结果如图3所示:
从图5可以看出,程序运行后提示了“ArrayIndexOutOfBoundsException”即数组角标越界异常的错误。
出现这个异常的原因是数组的长度为4,其索引范围为0~3,文件中的第4行代码使用索引4来访问元素时超出了数组的索引范围。所谓异常指程序中出现的错误,它会报告出错的异常类型、出错的行号以及出错的原因。
2.在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常,接下来通过一个案例来演示这种异常,如文件4所示。
文件4 Example21.java
public class Example21 {
public static void main(String[] args) {
int[] arr = new int[3]; // 定义一个长度为3的数组
arr[0] = 5; // 为数组的第一个元素赋值
System.out.println("arr[0]=" + arr[0]); // 访问数组的元素
arr = null; // 将变量arr置为null
System.out.println("arr[0]=" + arr[0]); // 再次访问数组的元素
}
}
运行结果如图6所示:
从图6可以看出,文件4中的第4、5行代码都能通过变量arr正常地操作数组,而在第6行代码将变量置为null后,在第7行代码再次访问数组时就出现了“java.lang.NullPointerException”的异常信息,即空指针异常。