String 是 Java 使用頻率最高的類,也是面試必考點。本文系統整理 String 的創建方式、22 個核心方法分類詳解、類型轉換、底層不可變機制及性能陷阱。
| 方式 | 代碼示例 | 說明 |
|---|---|---|
| 字面量 (推薦) | String s = "hello"; | 常量池複用,相同內容指向同一對象 |
| 無參構造 | new String() | 空字符串 "" |
| 字符串拷貝 | new String("hello") | 堆中創建新對象,不推薦 |
| char[] 轉換 | new String(new char[]{'a','b'}) | 複製數組內容 |
| char[] 部分 | new String(chars, offset, count) | 截取數組段構建 |
| StringBuffer 轉換 | new String(buffer) | 線程安全轉換 |
| StringBuilder 轉換 | new String(builder) | 高性能轉換 |
| byte[] 解碼 | new String(bytes, StandardCharsets.UTF_8) | 指定編碼,**必須指定編碼** |
length() // 長度 (char 數量)
charAt(int index) // 指定位置字符
codePointAt(int index) // 碼點 (支持增補字符)
getBytes(Charset charset) // 編碼為 byte[]
toCharArray() // 複製為 char[]
indexOf(String str) // 首次出現索引
indexOf(String str, int fromIndex)
lastIndexOf(String str) // 最後出現索引
contains(CharSequence s) // 是否包含 (底層 indexOf)
startsWith(String prefix) // 前綴匹配
endsWith(String suffix) // 後綴匹配
matches(String regex) // 正則全匹配
equals(Object obj) // 內容相等 (區分大小寫)
equalsIgnoreCase(String s) // 忽略大小寫相等
compareTo(String s) // 字典序比較 (按碼點)
compareToIgnoreCase(String s)
regionMatches(...) // 區域匹配 (可忽略大小寫)
substring(int begin) // 從 begin 到結尾
substring(int begin, int end) // [begin, end) 左閉右開
split(String regex) // 正則分割,返回 String[]
split(String regex, int limit) // limit 控制結果長度
trim() // 去除首尾空白字符 (≤ U+0020)
strip() / stripLeading() / stripTrailing() // JDK 11+ Unicode 感知去空白
replace(char old, char new) // 字符替換
replace(CharSequence t, CharSequence r) // 序列替換
replaceAll(String regex, String repl) // 正則替換全部
replaceFirst(String regex, String repl) // 正則替換首個
toLowerCase(Locale locale) // 轉小寫 (指定 Locale 避免土耳其語問題)
toUpperCase(Locale locale) // 轉大寫
valueOf(Object obj) // 任意對象轉字符串 (null → "null")
valueOf(char[] data) // char[] → String
valueOf(boolean/int/long/float/double/char) // 基本類型 → String
format(String fmt, Object... args) // 格式化 (類似 sprintf)
join(CharSequence delim, CharSequence... elements) // JDK 8+ 拼接
// 推薦:valueOf (null 安全)
String s1 = String.valueOf(123); // "123"
String s2 = String.valueOf(12.34); // "12.34"
String s3 = String.valueOf(true); // "true"
// 簡潔但隱含對象創建
String s4 = 123 + ""; // "123"
// 格式化
String s5 = String.format("%,d", 1000000); // "1,000,000"
String s6 = String.format("%.2f%%", 99.5); // "99.50%"
int i = Integer.parseInt("123");
long l = Long.parseLong("12345678901");
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true"); // 只識別 "true" (忽略大小寫)
// 進制轉換
int hex = Integer.parseInt("FF", 16); // 255
int bin = Integer.parseInt("1010", 2); // 10
public final class String implements Serializable, Comparable<String> {
// 緊湊字符串:Latin-1 (1 byte/char) 或 UTF-16 (2 bytes/char)
private final byte[] value;
private final byte coder; // 0=LATIN1, 1=UTF16
private int hash; // 默認 0,懶加載緩存
// ...
}
final 類、final 數組、無 setter → 不可變// 災難:循環 10萬次創建 10萬 StringBuilder + 10萬 String + 10萬 char[]
String s = "";
for (int i = 0; i < 100000; i++) s += "a";
// 正確:單一 StringBuilder
StringBuilder sb = new StringBuilder(100000);
for (int i = 0; i < 100000; i++) sb.append("a");
String result = sb.toString();
String a = "hello";
String b = "hello";
String c = new String("hello");
String d = c.intern(); // 手動入池
a == b // true (同一池對象)
a == c // false (堆對象)
a == d // true (intern 返回池引用)
isBlank() // 空或僅含空白字符
lines() // 按行分割為 Stream
strip() // Unicode 感知去首尾空白
stripLeading() // 去前導空白
stripTrailing() // 去尾隨空白
repeat(int n) // 重複 n 次
"=".repeat(80) // "================================================================================"
String s = new String("abc") 創建幾個對象?1 或 2 (常量池有 "abc" 則 1,無則 2)String.intern() 作用?將堆對象引用放入常量池,返回池中引用substring 會內存洩漏嗎?JDK 6 是 (共享 value 數組),JDK 7+ 否 (複製數組)