(一)数组的定义及特点
定义:
数组是存储相同数据类型元素的有序集合,可以看成相同类型元素的集合,在内存中是一段连续的空间。通过索引访问元素,且索引从0开始。
特点:
1.数组中存放的元素其类型相同(可以是基本类型或对象类型)。
2.数组的空间,即内存,连续分配,访问高效。
3.每个空间都有自己的编号,起始位置的编号为0,即数组的下标,也叫索引。
(二)数组的创建及初始化
数组的创建:
方式一(推荐):
数据类型[] 数组名;
//如:int[] arr;
方式二:(C语言风格,不推荐)
数据类型 数组名[];
//如 int arr[];
数组的初始化:
数组的初始化主要分为静态初始化和动态初始化。
1.静态初始化:
声明时直接赋值。在创建数组时,不直接指定数据元素个数,而是直接将具体的数据内容进行指定。
语法格式一:
数据类型[] 数组名 = new 数据类型[]{data1,data2,data3...datan};
例如:
int[] array6 = new int[]{1,2,3,4,5,6,7};
double[] array7 = new double[]{1.0, 2.0, 3.4, 5.6};
char[] array8 = new char[]{'1','A','a','对'};
boolean[] array9 = new boolean[]{true,false};
String[] array10 = new String[]{"hello","WORLD","123","!!!","你好"};
语法格式二:
语法格式二省去了new 数据类型[],博主习惯称之为“省略格式”。
数据类型[] 数组名 = {data1,data2,data3...datan};
例如:
int[] array1 = {1,2,3,4,5,6,7};
double[] array2 = {1.0, 2.0, 3.4, 5.6};
char[] array3 = {'1','A','a','对'};
boolean[] array4 = {true,false};
String[] array5 = {"hello","WORLD","123","!!!","你好"};
注意:
①语法格式一和语法格式二创建出来的数组完全一样,二者只是语法上的精简,本质上都一样。
虽然语法格式二省去了new 数据类型[],但是编译器编译代码时会自动补齐。
②静态初始化,在等号后的"[ ]"里,不能加数字,即不用指明数组长度。静态初始化虽然没有指明长度,但编译器在编译时会根据{}中的元素个数来确定数组的长度。
③静态初始化时,“{ }”中的数据类型必须与“[ ]”前的数据类型一致。
2.动态初始化:
在创建数组时,直接指定数组中数据元素的个数。此时初始化需要手动赋值。若只是动态创建数组,没有初始化值,Java会自动赋值为默认值。
语法格式:
数据类型[] 数组名 = new 数据类型[元素个数];
例如:
int[] array11 = new int[7]; // 动态创建数组
array11[0] = 1; // 手动赋值
double[] array12 = new double[4];
array12[2] = 2.3;
char[] array13 = new char[4];
array13[1] = 'a';
boolean[] array14 = new boolean[2];
array14[1] = true;
String[] array15 = new String[5];
array15[2] = "aaa";
3.静态初始化和动态初始化也可以分为两步,但省略格式不行:
//动态初始化
int[] arr1;
arr1 = new int[10];
//静态初始化
int[] arr2;
arr2 = new int[]{1,2,3,4,5,6,7};
注意:省略格式不能拆分,否则编译失败。省略格式只能在定义的同时进行赋值。
int[] arr3;
arr3 = {1,2,2,3,4};
//编译失败
4.没有对数组进行初始化时,数组中元素有其默认值。
如果没有对数组进行初始化,数组中元素有其默认值。
(1)如果数组中存储元素类型为基本数据类型,默认值为基本数据类型对应的默认值。如下表:
类型 | 默认值 |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0 |
char | /u0000 |
boolean | false |
(2)如果数组中存储元素类型为引用类型(这里指String类型),默认值为null
(三)数组的访问与遍历
1.访问数组中的元素
数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号就称为数组的下标,数组可以通过下标访问其任意位置的元素。
例:
int[]array = new int[]{10, 20, 30, 40, 50};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println(array[4]);
执行结果如图所示,按照数组下标访问数组元素:
也可以通过数组下标对数组中元素进行修改。
例:
int[]array = new int[]{10, 20, 30, 40, 50};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println(array[4]);
// 也可以通过[]对数组中的元素进行修改
array[0] = 100;
System.out.println(array[0]);
输出第一个元素:
注意:
①数组是一段连续的内存空间,因此支持随机访问,即通过下标访问,快速访问数组中任意位置的元素。
②下标从0开始,介于[0,n)之间,不包含n,n为数组元素个数。
③在Java中,数组不能越界,否则会报出下标越界异常。
例:
int[] array1 = {1, 2, 3};
System.out.println(array1[3]);
// 数组中只有3个元素,下标一次为:0 1 2,array[3]下标越界
数组array1中只有3个元素,下标依次为:0 1 2,array[3]下标越界 。代码执行结果为:
访问索引超出范围时抛出数组索引越界异常:ArrayIndexOutOfBoundsException
tips:与C语言作区分:C语言中数组索引越界,有时候报错,有时候不报错,比较随机。而在Java中,数组越界一定会报错。所以在使用数组时,一定谨防数组下标越界。
2.遍历数组
遍历是指将数组中的所有元素都访问一遍。而访问是指对数组中的元素进行某种操作。可以点击目录直接跳到本模块的遍历数组总结部分。
例:打印
int[]array = new int[]{10, 20, 30, 40, 50};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println(array[4]);
上述代码可以做到遍历数组并打印,但问题随之出现:
(1)如果数组中增加了一个元素,就需要增加一条打印语句。
(2)如果输入中有100或者10000个元素,就需要写100或者10000打印语句。
(3)如果现在要把打印修改为给数组中每个元素+1,修改起来超级麻烦。
通过观察代码可以发现,对数组中每个元素的操作都是相同的,则可以使用循环来进行打印。
for(int i = 0; i < 5; i++){
System.out.println(array[i]);
}
这就解决了上述三个问题中的(2)(3),(1)尚未解决。
动态获取数组长度就可以解决(1),Java中,可以通过下述格式直接获取数组的长度:
数组对象.length
例:
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
以上是普通for循环遍历数组,也可以使用增强for循环for-each遍历数组。
for (int num : array) {
System.out.println(num);
}
遍历数组总结:
第一种是普通for循环遍历,语法格式为:
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
第二种是增强for循环(for-each)遍历,语法格式为:
for (int num : array) {
System.out.println(num);
}
表示用num来接收数组array中的每一个值。
注意:
① for-each循环是for循环的另外一种使用方式,能够更方便的完成对数组的遍历,可以避免循环条件和更新语句写错。
② 与for循环相比,for-each循环只是拿到数组中的值,拿不到下标。