數組的聲明與初始化
數組是Java中存儲多個相同類型數據的容器,你可以把它想象成一排整齊的抽屜,每個抽屜只能放特定類型的數據。在Java中聲明和初始化數組有三種常用方式,我們通過學生成績管理的場景來理解:
靜態初始化:已知所有元素值時使用
當你已經明確知道每個位置的元素值時,直接在創建數組時賦值:
// 聲明並初始化一個存儲5名學生成績的數組
int[] scores = {90, 85, 95, 88, 92};
System.out.println("數組長度:" + scores.length); // 輸出:數組長度:5
System.out.println("第一個學生成績:" + scores[0]); // 輸出:第一個學生成績:90
這種方式會自動根據提供的元素數量確定數組長度,注意數組索引從0開始,就像我們數東西從第1個開始,但計算機從0開始計數。
動態初始化:已知長度但元素值需後續確定
當你知道需要存儲多少個數據,但具體值還不確定時(比如需要從鍵盤輸入):
// 創建一個能存儲3門課程名稱的數組,初始值為null
String[] courses = new String[3];
// 後續為數組元素賦值
courses[0] = "Java基礎";
courses[1] = "數據結構";
courses[2] = "數據庫原理";
// 嘗試訪問不存在的索引會報錯
// System.out.println(courses[3]); // 此行會拋出ArrayIndexOutOfBoundsException
這裏new String[3]告訴JVM創建一個長度為3的字符串數組,每個元素初始為null。
默認初始化:數組作為成員變量時的隱式初始化
當數組作為類的成員變量時,JVM會自動為其初始化默認值:
public class Student {
// 成員變量數組會被默認初始化
private int[] ages; // int類型數組默認值為0
public void printAges() {
ages = new int[2]; // 動態初始化後
System.out.println("默認值:" + ages[0]); // 輸出:默認值:0
}
public static void main(String[] args) {
new Student().printAges();
}
}
不同數據類型的默認值不同:整數類型為0,浮點類型為0.0,布爾類型為false,引用類型為null。
數組訪問與遍歷
數組索引規則
數組元素通過索引訪問,就像通過抽屜編號找到對應的抽屜。Java數組的索引從0開始,最大索引為數組長度-1。例如長度為5的數組,有效索引是0-4。
數組內存結構
理解數組在內存中的存儲方式有助於避免常見錯誤:
從圖中可以看到:
- 數組變量(如a)存儲在棧內存中,指向堆內存中的實際數組對象
- 數組長度(a.length)是數組對象的屬性,對於二維數組a[0].length表示第一個子數組的長度
- 數組元素在堆內存中連續存儲,通過索引快速訪問
遍歷數組的兩種方式
1. 普通for循環:需要索引時使用
int[] numbers = {2, 4, 6, 8, 10};
// 計算數組所有元素的和
int sum = 0;
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
System.out.println("索引" + i + "的值:" + numbers[i]);
}
System.out.println("數組元素總和:" + sum); // 輸出:數組元素總和:30
2. 增強for循環(for-each):僅遍歷元素時使用
String[] fruits = {"蘋果", "香蕉", "橙子"};
System.out.println("水果列表:");
for (String fruit : fruits) { // 讀作"for each fruit in fruits"
System.out.println(fruit);
}
運行結果:
水果列表:
蘋果
香蕉
橙子
增強for循環的優點是代碼簡潔,無需關心索引,但缺點是無法獲取當前元素的索引位置。
多維數組
多維數組可以理解為"數組的數組",最常用的是二維數組,類似於表格或Excel工作表。
二維數組的聲明與初始化
// 方式1:靜態初始化一個3行2列的二維數組
int[][] matrix = {
{1, 2},
{3, 4},
{5, 6}
};
// 方式2:動態初始化一個2行3列的二維數組
int[][] scores = new int[2][3];
scores[0][0] = 90; // 第1個學生第1門課成績
scores[0][1] = 85; // 第1個學生第2門課成績
scores[0][2] = 92; // 第1個學生第3門課成績
scores[1][0] = 88; // 第2個學生第1門課成績
// ...以此類推
二維數組的遍歷
使用嵌套循環遍歷二維數組:
// 遍歷matrix數組並打印
for (int i = 0; i < matrix.length; i++) { // 外層循環控制行數
for (int j = 0; j < matrix[i].length; j++) { // 內層循環控制列數
System.out.print(matrix[i][j] + " ");
}
System.out.println(); // 每行結束換行
}
運行結果:
1 2
3 4
5 6
注意:Java中的二維數組可以是不規則的,即每行的列數可以不同:
int[][] irregularArray = {
{1, 2},
{3},
{4, 5, 6}
};
字符串創建與常用方法
字符串是Java中最常用的類之一,用於表示文本數據。Java提供了String、StringBuffer和StringBuilder三個類來處理字符串,它們各有特點:
- String:不可變字符串,適合內容不常變化的場景
- StringBuffer:可變字符串,線程安全,性能稍低
- StringBuilder:可變字符串,非線程安全,性能高(推薦單線程環境使用)
String類的常用方法
以下是實際開發中最常用的String方法:
String str = " Hello Java World ";
// 1. 獲取字符串長度
System.out.println("長度:" + str.length()); // 輸出:長度:16
// 2. 去除首尾空格
String trimmed = str.trim();
System.out.println("去除空格後:'" + trimmed + "'"); // 輸出:去除空格後:'Hello Java World'
// 3. 字符串截取
String sub = str.substring(2, 7); // 從索引2開始到7(不包含7)
System.out.println("截取結果:" + sub); // 輸出:截取結果:Hello
// 4. 字符串查找
int index = str.indexOf("Java");
System.out.println("Java的位置:" + index); // 輸出:Java的位置:7
// 5. 字符串替換
String replaced = str.replace("Java", "Programming");
System.out.println("替換後:" + replaced); // 輸出:替換後: Hello Programming World
// 6. 大小寫轉換
System.out.println("小寫:" + str.toLowerCase());
System.out.println("大寫:" + str.toUpperCase());
// 7. 字符串比較
String s1 = "Hello";
String s2 = "hello";
System.out.println("是否相等(區分大小寫):" + s1.equals(s2)); // false
System.out.println("是否相等(不區分大小寫):" + s1.equalsIgnoreCase(s2)); // true
StringBuilder的使用
當需要頻繁修改字符串內容時,使用StringBuilder效率更高:
// 創建StringBuilder對象
StringBuilder sb = new StringBuilder();
// 追加內容
sb.append("Hello");
sb.append(" ");
sb.append("World");
sb.append("!");
// 插入內容
sb.insert(5, " Java"); // 在索引5處插入
// 轉換為String
String result = sb.toString();
System.out.println(result); // 輸出:Hello Java World!
數組與字符串轉換
在實際開發中,經常需要在數組和字符串之間進行轉換,Java提供了便捷的方法:
字符串轉數組:String.split()
String str = "apple,banana,orange";
// 使用逗號分割字符串
String[] fruits = str.split(",");
System.out.println("分割後的數組:");
for (String fruit : fruits) {
System.out.println(fruit);
}
運行結果:
分割後的數組:
apple
banana
orange
數組轉字符串:Arrays.toString()
import java.util.Arrays; // 需要導入Arrays類
int[] numbers = {1, 2, 3, 4, 5};
// 將數組轉換為字符串
String arrayStr = Arrays.toString(numbers);
System.out.println("數組轉字符串:" + arrayStr); // 輸出:數組轉字符串:[1, 2, 3, 4, 5]
字符數組與字符串互轉
// 字符串轉字符數組
String str = "Hello";
char[] chars = str.toCharArray();
System.out.println("字符數組長度:" + chars.length); // 輸出:字符數組長度:5
// 字符數組轉字符串
char[] charArray = {'W', 'o', 'r', 'l', 'd'};
String newStr = new String(charArray);
System.out.println("新字符串:" + newStr); // 輸出:新字符串:World
常見異常處理
在使用數組和字符串時,初學者最容易遇到兩種異常:數組越界異常和空指針異常。
數組越界異常
產生原因:訪問了超出數組索引範圍的位置。
int[] numbers = {1, 2, 3};
System.out.println(numbers[3]); // 錯誤!數組長度為3,有效索引是0-2
運行結果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at ArrayExample.main(ArrayExample.java:5)
規避方法:使用數組時始終確保索引在0到array.length - 1範圍內:
int[] numbers = {1, 2, 3};
// 安全的循環方式
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
空指針異常
產生原因:當一個對象為null時,調用其方法或訪問其屬性。
String str = null;
System.out.println(str.length()); // 錯誤!str為null,沒有length()方法
運行結果:
Exception in thread "main" java.lang.NullPointerException
at StringExample.main(StringExample.java:3)
規避方法:使用對象前先檢查是否為null:
String str = null;
// 安全的處理方式
if (str != null) {
System.out.println(str.length());
} else {
System.out.println("字符串為空");
}
實踐案例
案例一:數組排序
使用Arrays.sort()方法對數組進行排序,這是開發中最常用的排序方式:
import java.util.Arrays;
public class ArraySortExample {
public static void main(String[] args) {
// 定義一個無序數組
int[] scores = {85, 92, 78, 90, 88};
System.out.println("排序前:" + Arrays.toString(scores));
// 排序數組(默認升序)
Arrays.sort(scores);
System.out.println("排序後:" + Arrays.toString(scores));
// 查找最高分(排序後最後一個元素)
System.out.println("最高分:" + scores[scores.length - 1]);
// 查找最低分(排序後第一個元素)
System.out.println("最低分:" + scores[0]);
}
}
運行結果:
排序前:[85, 92, 78, 90, 88]
排序後:[78, 85, 88, 90, 92]
最高分:92
最低分:78
案例二:字符串反轉
實現字符串反轉有多種方式,這裏介紹兩種常用方法:
方法一:使用StringBuilder的reverse()方法(推薦)
public class StringReverseExample {
public static void main(String[] args) {
String original = "Hello Java";
// 方法一:使用StringBuilder
StringBuilder sb = new StringBuilder(original);
String reversed1 = sb.reverse().toString();
System.out.println("原字符串:" + original);
System.out.println("反轉後(方法一):" + reversed1);
// 方法二:使用字符數組
char[] chars = original.toCharArray();
String reversed2 = reverseWithArray(chars);
System.out.println("反轉後(方法二):" + reversed2);
}
// 使用字符數組手動反轉
private static String reverseWithArray(char[] chars) {
int left = 0;
int right = chars.length - 1;
while (left < right) {
// 交換左右兩個字符
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
// 移動指針
left++;
right--;
}
return new String(chars);
}
}
運行結果:
原字符串:Hello Java
反轉後(方法一):avaJ olleH
反轉後(方法二):avaJ olleH
總結與練習
今天我們學習了Java中數組和字符串的基礎知識,包括:
- 數組:聲明初始化、訪問遍歷、多維數組
- 字符串:String類常用方法、StringBuilder使用
- 轉換技巧:數組與字符串的相互轉換
- 異常處理:數組越界和空指針異常的規避
- 實踐案例:數組排序和字符串反轉
練習題
- 數組統計:創建一個int數組,統計其中偶數和奇數的個數。
- 字符串處理:編寫一個方法,將字符串中的每個單詞首字母大寫。
- 綜合練習:從控制枱輸入5個整數,排序後輸出,並計算平均值。
通過這些基礎知識的學習,你已經具備了處理批量數據和文本的能力,這是Java編程的重要基礎。明天我們將學習面向對象編程的基礎知識,進一步提升你的Java技能!