Java 中 String 為 不可變物件。所有「修改」操作實際上都會返回新的 String 物件,原物件不變。這是理解所有 String 方法行為的基礎。
| 方法 | 說明 | 範例 |
|---|---|---|
int length() | 返回字元數(UTF-16 代碼單元數) | "Hello".length() == 5 |
char charAt(int index) | 返回指定索引字元 | "ABC".charAt(1) == 'B' |
int indexOf(int ch) | 首次出現位置,無則 -1 | "ABAB".indexOf('A') == 0 |
int indexOf(String str) | 子字串首次出現位置 | "ABC".indexOf("BC") == 1 |
int indexOf(String str, int fromIndex) | 從指定位置開始搜尋 | "ABAB".indexOf("A", 1) == 2 |
int lastIndexOf(String str) | 反向搜尋最後出現位置 | "ABAB".lastIndexOf("A") == 2 |
| 方法 | 說明 | 注意事項 |
|---|---|---|
boolean contains(CharSequence s) | 是否包含指定子序列 | 等同 indexOf(s) >= 0 |
boolean isEmpty() | 長度是否為 0 | Java 6+,推薦用此替代 length() == 0 |
boolean isBlank() | 是否為空或僅含空白字元 | Java 11+,含空格、製表、換行等 |
boolean startsWith(String prefix) | 是否以指定前綴開頭 | 可用於檔案類型判斷 |
boolean endsWith(String suffix) | 是否以指定後綴結尾 | filename.endsWith(".java") |
boolean equals(Object obj) | 內容相等(區分大小寫) | 覆寫 Object.equals,**絕不用 == 比較內容** |
boolean equalsIgnoreCase(String str) | 忽略大小寫比較 | 效能略低於 equals |
// 字元陣列 → String
char[] chars = {'J', 'a', 'v', 'a'};
String s1 = new String(chars); // "Java"
String s2 = new String(chars, 1, 2); // "av" (offset=1, count=2)
String s3 = String.valueOf(chars); // 靜態方法,等同 new String(chars)
String s4 = String.copyValueOf(chars, 1, 2); // 同 valueOf
// String → 字元陣列
char[] arr = "Java".toCharArray(); // ['J','a','v','a']
String str = "中文";
// String → byte[](必須指定編碼!)
byte[] bytes = str.getBytes(StandardCharsets.UTF_8); // 推薦明確指定
// byte[] → String(必須指定編碼!)
String restored = new String(bytes, StandardCharsets.UTF_8);
警告:不指定編碼將使用平台預設編碼,導致跨平台亂碼。生產環境強制指定 StandardCharsets.UTF_8。
String s1 = String.valueOf(123); // "123"
String s2 = String.valueOf(45.67); // "45.67"
String s3 = String.valueOf(true); // "true"
// 等同於:123 + ""、String.valueOf() 效能略優
String s = "hello java";
// 字元替換
s.replace('a', 'o'); // "hello jovo"
// 字串替換(全部替換)
s.replace("java", "world"); // "hello world"
// 正則替換
s.replaceAll("\\s+", "-"); // "hello-java"
s.replaceFirst("\\d+", "#"); // 僅替換首個匹配
String csv = "張三,李四,王五";
// 簡單切割
String[] arr1 = csv.split(","); // ["張三", "李四", "王五"]
// 正則切割(限制結果長度)
String[] arr2 = csv.split(",", 2); // ["張三", "李四,王五"]
// 移除尾部空字串
String trailing = "a,b,c,,,";
trailing.split(","); // ["a", "b", "c"] 尾部空字串被丟棄
trailing.split(",", -1); // ["a", "b", "c", "", "", ""] 保留
String s = "abcdef";
// 從索引 2 到結尾
s.substring(2); // "cdef"
// 索引 2 到 4(不含 4)
s.substring(2, 4); // "cd"
// 注意:substring 共用底層 char[](Java 7u6 前),大字串切割可能記憶體洩漏
// 避免:new String(s.substring(2,4)) 強制複製
| 方法 | 說明 | 範例 |
|---|---|---|
toUpperCase() | 轉大寫 | "java".toUpperCase() == "JAVA" |
toLowerCase() | 轉小寫 | "JAVA".toLowerCase() == "java" |
trim() | 移除首尾空白字元(≤ U+0020) | " hi ".trim() == "hi" |
strip() | 移除首尾 Unicode 空白字元 | Java 11+,比 trim 更完整 |
compareTo(String s) | 字典序比較 | 返回負/0/正,可用於排序 |
compareToIgnoreCase(String s) | 忽略大小寫比較 |
public class StringDemo {
public static void main(String[] args) {
String raw = " User:Admin, Role:SuperAdmin, Status:Active ";
// 1. 清理
String cleaned = raw.strip();
// 2. 解析
String[] parts = cleaned.split(", ");
Map map = new LinkedHashMap<>();
for (String part : parts) {
String[] kv = part.split(":");
if (kv.length == 2) map.put(kv[0], kv[1]);
}
// 3. 判斷權限
boolean isAdmin = "Admin".equalsIgnoreCase(map.get("User"));
boolean isActive = "Active".equals(map.get("Status"));
// 4. 格式化輸出
String output = String.format("用戶: %s | 角色: %s | 狀態: %s | 權限: %s",
map.get("User"), map.get("Role"), map.get("Status"),
isAdmin && isActive ? "完整" : "受限");
System.out.println(output);
}
}
StringBuilder(單執行緒)或 StringBuffer(多執行緒)Pattern.compile()new String(sub) 斷開引用掌握 String 核心 API,關鍵在於理解不可變性、編碼轉換、正則與普通方法的區別。實務中善用 strip()、isBlank()(Java 11+)、String.format() 等現代 API,能寫出更健壯、更易讀的程式碼。