架构图
p.s 由于地区的术语不同,文中会以"阵列"代替"数组",请见谅
创建阵列
作为参考数据类型的一员,阵列(array)在java中其实就是一个物件,因此后续处理阵列时需要将物件的概念套用上,对于学过C/C++的人可能需要一点思想上的转换
首先我们来看看在java当中,是如何创建一个阵列的。java宣告时可将[]
置于变数名前方或后方,但为了与C/C++做出区别,官方推荐将[]
放到变数前方:
int[] arr1; // 推荐
int arr2[]; // 也可以
不过宣告完阵列变数arr
以后,阵列事实上并不真正存在
对于一个阵列来说,他具备一个物件的特性,也就代表目前的arr
只是一个阵列物件的参考名而已。这个阶段编译器只知道这个整数阵列可能会指向一个阵列物件,所以在宣告阵列变数后还需要使用new在Heap当中生成一个真正的整数阵列,然后再指定给arr
下面几种方法均可以生成一个阵列物件:
/* 方法1 */
int[] arr1;
arr1 = new int[10];
/* 方法2 */
int[] arr2 = new int[10];
/* 方法3 */
int[] arr3 = new int[]{
1,2,3,4,5,6,7,8,9,10};
/* 方法4 */
int[] arr3 = {
1,2,3,4,5,6,7,8,9,10}; // 可以省略掉 int[]
初始化需要注意的几个问题
- 阵列一旦建立,长度就固定了,若需要更改只能重新建立一个长度更长的阵列
- 数据类型为必填项
- 若是使用直接赋值法(例如方法3、4)可以忽略阵列长度
- 在java当中所有阵列都是动态分配的
阵列初始值
使用new建立阵列后,有别于其他变数类型,每个阵列元素都会自动分配一个预设值(物件特性)
- 对于引用资料类型或任何物件(ex. String或一个阵列物件) →
null
- 对于
byte
/short
/int
/long
→ 0 - 对于
float
/double
→ 0.0 - 对于字元 →
null
字元\u0000
- 对于布林 →
false
越界
当阵列index小于0或者等于或大于当前阵列长度时就会发生越界,例如我们故意将index自增到与阵列常相等(a.length
为阵列长度)
class Main {
public static void main(String[] args){
int[] arr = {
1,2,3,4,5,6,7};
for(int i=0; i<=arr.length; i++){
System.out.println("arr["+i+"] = " + arr[i]); // i=7时发生异常
}
}
}
输出结果:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
arr[5] = 6
arr[6] = 7
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7
at Main.main(Main.java:15)
我们可以看到程式抛出例外资讯ArrayIndexOutOfBoundsException
。不像C/C++一样,编译器不会事先检查阵列是否越界,而是在执行过程中处理意外(Runtime Exception)
有几种方法可以解决例外的产生,分别是撰写例外处理程式或者使用For-each loop迴圈
使用例外处理
我们把越界问题调整一下,将上述程式的起始值设定成-1,终值设定为<=arr.length+1
,产生三次越界。与此同时我们也已经知道越界异常退跳出ArrayIndexOutOfBoundsException
,所以可以利用try catch去捕捉这个异常:
class Main {
public static void main(String[] args){
int[] arr = {
1,2,3,4,5,6,7};
for(int i=-1; i<=arr.length+1; i++){
try {
System.out.println("arr["+i+"] = " + arr[i]);
} catch(ArrayIndexOutOfBoundsException e){
// 捕捉越界例外发生
System.out.println("发生越界!"); // 通知例外发生
continue; // 直接进入下一次循环
}
}
}
}
输出结果:
发生越界!
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
arr[5] = 6
arr[6] = 7
发生越界!
发生越界!
如此一来程式执行时发生越界问题时能够即时通报,并继续运行值到跳出迴圈。下一小节将会继续探讨避免越界例外发生的另一个解决方法: For-each loop
For-each loop
For-each loop又称为增强型for迴圈,它是java迴圈的一种语法糖,具备以下几种好处:
- 书写较为简洁
- 方便遍历搜寻
- 避免越界例外产生
不过若是有特殊需求,例如指定index范围或是程式逻辑涉及到阵列index时还是建议使用原本的for loop迴圈。基本的增强型for迴圈逻辑结构如下所示:
class Main {
public static void main(String[] args){
int[] arr = {
1,2,3,4,5,0,0,0};
for(int n:arr){
System.out.println(n);
}
}
}
输出结果:
1
2
3
4
5
0
0
0
增强型for迴圈会自动判断阵列的长度,并将阵列元素赋值给区域变数(n),直到所有阵列元素接访问为止。所以上述程式码其实相当于:
class Main {
public static void main(String[] args){
int[] arr1 = {
1,2,3