你好!之前在您的培訓中,我們使用過單個對象(和原始類型)。但是,如果我們需要處理一整組對象而不是一個對象怎麼辦?例如,假設我們要創建我們公司所有員工的生日列表。它應該包含 30 個字符串,格式如下:"Sarah Huffman, January 25" 我們將從稱為數組的特殊數據結構中獲益。如果我們將數組比作一個真實的對象,它非常類似於帶有保險箱的銀行金庫: 數組也由“盒子”組成。你可以在每個盒子裡放一些東西(一個元素)。要訪問一個元素,您需要知道它的框號(索引)。這是創建數組的方式:
每行代表一個
public class Main {
public static void main(String[] args) {
String [] birthdays = new String[10];
}
}
這裡我們創建了一個包含 10 個元素的數組。 您可以立即註意到數組的一些特徵:
- 它存儲定義明確的數據類型的元素。如果我們創建一個 String 數組,我們就不能在其中存儲任何其他內容。數據類型是在創建數組時指定的。這是它與保險箱(客戶可以在其中存放他或她想要的東西)的不同之處。
- 它的大小必須在創建數組時指定。您不能稍後指示它或在創建數組後更改其大小。
String [] birthdays = new String[10];
String birthdays [] = new String[10];
如果要將內容寫入數組,則需要指定要寫入值的框的索引。數組中的框從 0 開始編號。 從零開始計數是編程中非常常見的做法。你越快習慣它越好 :) 這意味著,如果你想在第一個盒子裡放一些值,你可以這樣做:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
}
}
現在 Jana 的生日存儲在我們的員工生日數組的第一個單元格中:您可以以類似的方式添加其他值:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
}
}
請注意,我們在第八個盒子中添加了 Rosie 的生日(你不會忘記為什麼 7 號盒子是第八個盒子吧?)。您可以看到我們還沒有填充所有其他單元格。我們不必按順序將值寫入數組。沒有這樣的要求。當然,按順序編寫元素可以更容易地跟踪有多少盒子是空閒的,有多少盒子被佔用,並且它可以防止數組出現“漏洞”。如果你想得到其中一個盒子裡的東西,那麼(就像保險箱一樣)你需要知道它的號碼。這是如何完成的:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
String rosieBirthday = birthdays[7];
System.out.println(rosieBirthday);
}
}
控制台輸出: Rosie Mills,1 月 3 日 我們創建了一個變量並告訴編譯器:“在birthdaysString
數組中找到索引為 7 的框,並將其中包含的值分配給變量rosieBirthday ”。這正是它所做的。使用數組時,我們可以使用特殊屬性輕鬆找到它們的長度:length。 String
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[7] = "Rosie Mills, January 3";
int birthdaysLength = birthdays.length;
System.out.println(birthdaysLength);
}
}
控制台輸出: 10 注意:該length
屬性存儲的是數組大小,而不是已滿的框數。我們的數組只存儲 3 個值,但我們在創建它時將其大小指定為 10。這正是該字段返回的值length
。為什麼這會派上用場?好吧,假設您想顯示所有生日的列表(以驗證沒有人被遺忘)。您可以在一個簡單的循環中執行此操作:
public class Main {
public static void main(String[] args) {
String birthdays [] = new String[10];
birthdays[0] = "Jana Russell, March 12";
birthdays[1] = "Landon Chan, May 18";
birthdays[2] = "Jeremiah Leonard, July 12";
birthdays [3] = "Kenny Russo, September 7";
birthdays[4] = "Tommie Barnes, November 9";
birthdays [5] = "Roman Baranov, August 14";
birthdays [6] = "Chanice Andersen, April 1";
birthdays[7] = "Rosie Mills, January 3";
birthdays [8] = "Keenan West, October 19";
birthdays [9] = "Abraham McArthur, May 3";
for (int i = 0; i < birthdays.length; i++) {
System.out.println(birthdays[i]);
}
}
}
在循環中,我們聲明變量i
,它被初始化為零。每次通過時,我們都會從數組中獲取索引為 i 的元素並顯示其值。循環將執行 10 次迭代,並且 i 將從 0 增加到 9——數字恰好是我們數組元素的索引!因此,我們將顯示從birthdays[0]到birthdays[9] 的所有值 。實際上,還有另一種創建數組的方法。例如,您可以int
像這樣創建一個 s 數組:
public class Main {
public static void main(String[] args) {
int numbers [] = {7, 12, 8, 4, 33, 79, 1, 16, 2};
}
}
這種技術稱為“快捷方式初始化”。這非常方便,因為我們同時創建了一個數組並用值填充它。我們不必明確指定數組大小:通過快捷方式初始化,該length
字段會自動設置。
public class Main {
public static void main(String[] args) {
int numbers [] = {7, 12, 8, 4, 33, 79, 1, 16, 2};
System.out.println(numbers.length);
}
}
控制台輸出: 9 現在,稍微介紹一下數組是如何存儲在內存中的。假設我們有一個包含三個Cat
對象的數組:
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public static void main(String[] args) {
Cat[] cats = new Cat[3];
cats[0] = new Cat("Thomas");
cats[1] = new Cat("Behemoth");
cats[2] = new Cat("Lionel Messi");
}
}
你需要在這裡了解一些事情:
-
在基元的情況下,數組存儲一組特定值(例如
int
s)。對於對象,數組存儲一組引用。
該cats
數組由三個元素組成,每個元素都是對一個對象的引用Cat
。每個引用都指向存儲相應對象的內存地址。 - 數組元素排列在內存中的單個塊中。這樣做是為了能夠快速有效地訪問它們。
cats
引用存儲所有對象(數組元素)的內存塊。Cats[0]
引用此塊中的特定地址。 理解數組不僅僅是存儲對像很重要:它本身就是一個對象。 這讓我們質疑我們是否不僅可以創建字符串數組或數字數組,還可以創建數組數組。答案是肯定的,我們可以!數組可以存儲任何對象,包括其他數組。這樣的數組稱為二維數組。如果我們用視覺來表示它,它會非常類似於一張普通的桌子。假設,我們要創建一個包含3 個數組的數組,每個數組可以存儲 10int
個。它看起來像這樣:
int
數組。第一個數組包含從 1 到 10 的數字,第二個數組 - 從 -1 到 -10,第三個 - 一組隨機數。這些數組中的每一個都存儲在我們的二維數組的盒子中。在代碼中,二維數組的初始化如下所示:
public static void main(String[] args) {
Cat[][] cats = new Cat[3][5];
}
我們的二維數組cats存儲了3 個數組,每個數組有 5 個盒子。如果我們想把一個對象放在第二個數組的第三個盒子裡,我們會這樣做:
public static void main(String[] args) {
Cat[][] cats = new Cat[3][5];
cats[1][2] = new Cat("Fluffy");
}
[1]
指示第二個數組,並[2]
指示該數組的第三個框。因為二維數組由多個數組組成,為了遍歷它並顯示它的所有值(或填充它的所有元素),我們需要一個嵌套循環:
for (int i = 0; i < cats.length; i++) {
for (int j = 0; j < cats[i].length; j++) {
System.out.println(cats[i][j]);
}
}
在外部循環(變量i
)中,我們遍歷二維數組中的所有數組。在內部循環(變量j
)中,我們遍歷每個數組的所有元素。結果,cats[0][0](第一個數組,第一個元素)將首先顯示,然後是cats[0][1](第一個數組,第二個元素)。在我們完成第一個數組後,我們將顯示cats[1][0]、cats[1][1]、cats[1][2]等。順便說一句,二維數組也支持速記初始化:
int[][] numbers = {{1,2,3}, {4,5,6}, {7,8,9}};
通常,我們會將二維數組聲明numbers
為int[3][3]
,但這種簡寫讓我們可以立即指定值。為什麼需要二維數組?好吧,您可以使用它來輕鬆地重現著名的“戰艦”遊戲: 在“戰艦”中,遊戲場的結構可以很容易地描述:一個由 10 個數組組成的二維數組,每個數組有 10 個元素。你創建兩個這樣的陣列(一個給你,一個給你的對手)
int[][] battleshipBoard1 = new int[10][10];
int[][] battleshipBoard2 = new int[10][10];
使用一些值(例如數字或符號)來填充與您的船隻位置相對應的元素,然後輪流調用特定元素的坐標:
- battleshipBoard1[0][2]!
- 錯過!battleshipBoard2[2][4]!
- 打!
- battleshipBoard2[2][5]!
- 打!
- battleshipBoard2[2][6]!,
- 沉沒!
GO TO FULL VERSION