[Java] 字串
目錄
前言
在 Java 中,字串代表一組字元,是 java.lang.String 類別的實例,Java 中的物件特性他都具備,不過字串有一些特殊的特性,是為了效能考量而設計的。
字串基礎
所謂字串,就是由多個得字元組成的序列,例如 "Hello" 就是一個字串,由 H、e、l、l、o 這幾個字元組成。
在 Java 中,我們使用"來表示字串,例如:
String str = "Hello";也因為他是字元組成的序列,所以我們可以查看它的長度,或是取得其中的字元。
String str = "Hello";
System.out.println(str.length()); // 5
System.out.println(str.charAt(0)); // H字串的特性
字串常量與字串池
開始前我們先來回達兩個問題
- 以下的程式片段結果是
true還是false?答案是char[] a = {'H', 'e', 'l', 'l', 'o'}; String str1 = new String(a); String str2 = new String(a); System.out.println(str1 == str2);false,因為new關鍵字會在記憶體中建立一個新的物件,所以str1和str2是不同的物件。 - 以下的程式片段結果是
true還是false?答案是String str1 = "Hello"; String str2 = "Hello"; System.out.println(str1 == str2);true,因為 Java 會將所有的字串常量放在字串池中,當我們宣告一個字串時,只要他的序列相同、大小寫相同,無倫他們出現過多少次,JVM 都只會建立一個 String 物件放在字串池中,如果你又建立了一個相同的字串,JVM 會先檢查字串池中是否已經有這個字串,如果有就直接返回這個字串的參考,不會再建立一個新的物件。如果沒有才會建立一個新的物件。
使用 "" 來宣告字串,我們就稱他為字串常量(String Literal),字串常量是不可變動(Immutable)的,也就是說一旦建立了字串常量,他的值就不能再改變了。
而這邊我們就要特別注意,如果你想要比較兩個字串是否相等,因為前面提到的字串池及使用new來建立字串物件,所以我們不能使用 == 來比較兩個字串是否相等,因為 == 是比較兩個物件的參考是否相等,而不是比較兩個物件的值是否相等,所以我們應該使用 equals() 方法來比較兩個字串是否相等。
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println(str1 == str2); // true
System.out.println(str1.equals(str2)); // true
System.out.println(str1 == str3); // false
System.out.println(str1.equals(str3)); // true
System.out.println(str3 == str4); // false不可變動(Immutable)字串
字串常量是不可變動的,這是因為 Java 的效能考量,當我們對字串做修改時,實際上是建立了一個新的字串物件,而原本的字串物件並沒有被改變,這樣會造成記憶體的浪費,所以 Java 設計成字串是不可變動的,這樣就不用擔心字串物件被修改。
String str = "Hello"; // 建立一個字串物件
str = str + " World"; // 在字串池中建立一個新的字串物件,也就是說現在有兩個字串物件,一個是 "Hello",一個是 "Hello World"
System.out.println(str); // Hello World我們來寫個程式來看看。從耗費記憶體的方式到效能考量的方式。輸出1+2+3...+100的字串
public class Main {
public static void main(String[] args) {
String str = "";
for (int i = 1; i <= 100; i++) {
str += i;
}
System.out.println(str);
}
}但以上的程式碼是不好的,因為每次迴圈都會建立一個新的字串物件,這樣會造成記憶體的浪費,所以我們應該使用 StringBuilder 或 StringBuffer 來處理字串。
public class Main {
public static void main(String[] args) {
StringBuilder str = new StringBuilder();
for (int i = 1; i <= 100; i++) {
str.append(i);
}
System.out.println(str.toString());
}
}在 Java 中,StringBuilder 和 StringBuffer 都是用來創建和操作可變的字串。它們的 API 都非常相似,但主要的區別在於 StringBuffer 是線程安全的,而 StringBuilder 不是。
- StringBuilder:
- 線程不安全
- 非同步、效能較好
- 如果單線程,建議使用 StringBuilder
- StringBuffer:
- 線程安全
- 同步、效能較差
- 如果多線程,建議使用 StringBuffer
字串常用方法
Java 中的字串有很多常用的方法,我們直接使用程式碼來看看。
String str = "Hello";
System.out.println(str.length()); // 5, 取得字串長度
System.out.println(str.charAt(0)); // H, 取得指定位置的字元
System.out.println(str.substring(1)); // ello, 取得指定位置之後的子字串
System.out.println(str.substring(1, 3)); // el, 取得指定位置之間的子字串
System.out.println(str.indexOf("l")); // 2, 取得指定字元第一次出現的位置
System.out.println(str.lastIndexOf("l")); // 3, 取得指定字元最後一次出現的位置
System.out.println(str.startsWith("H")); // true, 判斷字串是否以指定字元開頭
System.out.println(str.endsWith("o")); // true, 判斷字串是否以指定字元結尾
System.out.println(str.equals("Hello")); // true, 判斷字串是否與指定字串相等
System.out.println(str.equalsIgnoreCase("hello")); // true, 忽略大小寫判斷字串是否相等
System.out.println(str.toLowerCase()); // hello, 將字串轉換為小寫
System.out.println(str.toUpperCase()); // HELLO, 將字串轉換為大寫
System.out.println(str.trim()); // Hello, 移除字串前後的空白
System.out.println(str.replace("H", "h")); // hello, 取代字串中的字元
System.out.println(str.contains("l")); // true, 判斷字串是否包含指定字元
System.out.println(str.concat(" World")); // Hello World, 連接字串
System.out.println(str + " World"); // Hello World, 連接字串