5.5 Array initialization
陣列宣告與初始化
- 陣列在 Java 中是一系列相同類型的數據集合,可以存儲 primitive 或 object reference
- 定義一個陣列,只要在類型名稱後面加上方括號
[]
int[] a1;
- 也可以放在 identifier 後面,兩種含意是一樣的
int a1[];
- 編譯器不允許指定 array 大小,宣告後拿到的只是對 array 的 reference,但沒有給 array object 本身分配任何空間
- 例如
int a1[5];
這樣的宣告是不合法的
- 例如
- 若要創建陣列並分配記憶體空間,需要使用初始化表達式。初始化可以在宣告後的任何地方進行,只要在變數使用前完成即可
- 也可以使用一種特殊的初始化,必須使用在創建 array 的地方,用大括號組成,儲存空間的分配 (等同使用 new)將由編譯器負責
- 這種初始化方式是 Java 的一種「匿名陣列」初始化,並且這種方式初始化後,陣列的長度和元素都將固定
int[] a1 = {1, 2, 3, 4, 5};
陣列的引用和修改
- 在沒有 array 的時候定義 array reference,是由於在 Java 中可以將一個 array assign 給另外一個 array,實際只是複製一個 reference
int[] a2;
a2 = a1;
public class ArraysOfPrimitives {
public static void main(String[] args) {
int[] a1 = { 1, 2, 3, 4, 5 };
int[] a2;
a2 = a1;
for(int i = 0; i < a2.length; i++)
a2[i] = a2[i] + 1;
for(int i = 0; i < a1.length; i++)
System.out.println("a1[" + i + "] = " + a1[i]);
}
} /* Output:
a1[0] = 2
a1[1] = 3
a1[2] = 4
a1[3] = 5
a1[4] = 6
*/
信息
- 所有 array 都有一個固有成員 length,可以透過它知道 array 內包含多少元 素,但不能對其修改
- 從元素0開始,因此能使用的最大下標是 length - 1
- 一旦超過,就會出現運行時錯誤
陣列的動態創建和自動初始化
- 若編寫代碼時不確定需要多少元素,可使用
new
指令動態創建陣列- 基本數據類型的陣列會自動初始化為預設值(如
int
為0
) - object 類型的陣列則初始化為
null
- 基本數據類型的陣列會自動初始化為預設值(如
public class ArrayNew {
public static void main(String[] args) {
int[] a;
Random rand = new Random(47);
a = new int[rand.nextInt(20)];
System.out.println("length of a = " + a.length);
System.out.println(Arrays.toString(a));
}
} /* Output:
length of a = 18
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
*/
- array 大小通過
Random.nextInt()
隨機決定 - primitive 類型會自動初始化成空值 (
0
、false
) - 也可以在定義的同時初始化:
int[] a = new int[rand.nextInt(20)];
- 如果建立了一個非 primitive 的 array,那就是建立了一個 reference 的 array
- 未初始化的
Integer
陣列元素預設為null
,如果直接使用可能會導致NullPointerException
- 未初始化的
包裝器類型陣列的使用
public class ArrayClassObj {
public static void main(String[] args) {
Random rand = new Random(47);
Integer[] a = new Integer[rand.nextInt(20)];
System.out.println("length of a = " + a.length);
for(int i = 0; i < a.length; i++)
a[i] = rand.nextInt(500); // Autoboxing
System.out.println(Arrays.toString(a));
}
} /* Output: (Sample)
length of a = 18
[55, 193, 361, 461, 429, 368, 200, 22, 207, 288, 128, 51, 89, 309, 278, 498, 361, 20]
*/
- 這邊用的是包裝器
Integer
,是 class 而非 primitive - 這邊即使使用
new
建立 array 之後,它還只是一個 reference array,直到透過建立新的Integer
object 初始化才算結束 - 如果忘了建立 object 而試著使用 array 中的空 reference,就會產生runtime error
初始化 Object 類型的陣列
- 在定義處的地方初始化可以使用其他型式
- 對於 Object 類型的陣列,可以在定義時使用大括號
{}
進行初始化。這包括直接使用new Integer()
來創建對象,或 利用自動裝箱(autoboxing)直接將基本類型賦值給包裝類型
public class ArrayInit {
public static void main(String[] args) {
Integer[] a = {
new Integer(1),
new Integer(2),
3, // Autoboxing
};
Integer[] b = new Integer[]{
new Integer(1),
new Integer(2),
3, // Autoboxing
};
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
} /* Output:
[1, 2, 3]
[1, 2, 3]
*/
- 列表最後一個逗號是可選的
使用陣列傳遞參數給方法
- 陣列可以用作方法的參數,從而允許在不同方法間傳遞多個數據。這是一種在方法調用時動態創建並初始化陣列的方式,特別是當使用字串陣列作為參數傳遞給其他方法時
public class DynamicArray {
public static void main(String[] args) {
Other.main(new String[]{ "fiddle", "de", "dum" });
}
}
class Other {
public static void main(String[] args) {
for(String s : args)
System.out.print(s + " ");
}
} /* Output:
fiddle de dum
*/