Java11在String類上引入了一系列新的API增強,這些改進顯著提升了開發者在處理字符串時的便捷性和效率。
以下是Java11中增強String API的主要新特性:
- String.repeat():重復給定次數的字符串。返回連接的字符串。
- String.isBlank():檢查字符串是否為空或只有空格。
- String.strip():刪除前導和尾隨空格。
- String.stripLeading():刪除前導空格。
- String.stripTrailing():刪除尾隨空格。
- String.lines():返回多行字符串的行流。
String.repeat()
repeat
方法允許你重復一個字符串指定的次數。這在需要快速生成重復字符串的場景中非常有用。
示例:
String str = "abc".repeat(3);
System.out.println(str); // 結果為 "abcabcabc"
String.isBlank()
isBlank
方法檢查一個字符串是否為空或者僅包含空白字符(如空格、制表符、換行符等)。這是一個非常實用的方法,可以幫助你判斷用戶輸入是否有效。
示例:
System.out.println("".isBlank()); // 輸出 true
System.out.println(" ".isBlank()); // 輸出 true
System.out.println("\t".isBlank()); // 輸出 true
System.out.println("\n".isBlank()); // 輸出 true
System.out.println("hello".isBlank()); // 輸出 false
String.strip(), String.stripLeading(), String.stripTrailing()
這三個方法用于刪除字符串的前導、尾隨或前導和尾隨的空白字符。
strip()
:刪除字符串的前導和尾隨空白字符。stripLeading()
:僅刪除字符串的前導空白字符。stripTrailing()
:僅刪除字符串的尾隨空白字符。
示例:
String str = " hello, world! ";
System.out.println(str.strip()); // 輸出 "hello, world!"
System.out.println(str.stripLeading()); // 輸出 "hello, world! "
System.out.println(str.stripTrailing()); // 輸出 " hello, world!"
String.lines()
lines
方法將字符串按行分隔,并返回一個Stream<String>
,其中每個元素是字符串中的一行。這對于處理多行文本或文件內容非常有用。
示例:
String str = "line1\nline2\nline3";
str.lines().forEach(System.out::println); // 分別打印三行
String類的重要變化
Java中的String
類在不同版本之間經歷了一些重要的變化。以下是一些關鍵的變化:
Java6及之前
String
類內部使用字符數組(char[]
)來存儲字符串數據。每個字符占用兩個字節(16位),因為Java使用UTF-16編碼。
Java7
Java7引入了String
類的內部優化,增加了一個稱為“字符串池”的概念。這種優化可以減少內存使用和提高性能。
Java 9
Java9之前中的String是使用char[]數組來存儲字符的,每個字符通常占用兩個字節(在UTF-16編碼下)。然而,對于只包含 ASCII字符(或LATIN-1字符集)的字符串,這會導致大量的空間浪費,因為ASCII字符實際上只需要一個字節來存儲。
Java9對String
類進行了重大改動,改用byte[]
數組來存儲字符串數據,并通過一個coder
字段來標識使用的是Latin-1還是UTF-16編碼。對于僅包含Latin-1字符的字符串,這種方式可以節省一半的內存。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {private final byte[] value;private final byte coder;// ...
}
可以通過下面的代碼來觀察String內部使用Latin-1或UTF-16編碼時,內部數組的情況和coder
字段的標識:
package com.morris.java11;import java.lang.reflect.Field;public class StringCoderDemo {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Field valueField = String.class.getDeclaredField("value");valueField.setAccessible(true);Field coderField = String.class.getDeclaredField("coder");coderField.setAccessible(true);String aa = "hello";System.out.println(((byte[])valueField.get(aa)).length); // 5System.out.println(coderField.get(aa)); // 0String bb = "中a";System.out.println(((byte[])valueField.get(bb)).length); // 4System.out.println(coderField.get(bb)); // }
}
運行時增加此--add-opens java.base/java.lang=ALL-UNNAMED
JVM參數,否則會拋出Unable to make field private final byte[] java.lang.String.value accessible
錯誤。
Java 11
Java 11增加了一些實用的方法,如strip()
, isBlank()
, lines()
, repeat()
等,提升了字符串處理的便利性。內部結構保持與Java 9一致。
這些變化主要是為了提高性能和減少內存使用,同時也增加了字符串操作的便利性。每個版本的改進都對開發者在處理字符串時帶來了不同程度的影響。
Compressed Strings與Compact Strings
Compressed Strings與Compact Strings是Java在處理字符串時所采用的兩種不同機制,它們在Java的不同版本中有所體現,具體區別如下:
Compressed Strings(壓縮字符串):
- 引入版本:Java 6。
- 特性:Compressed Strings對于每個字符占用一個字節(one byte per character)的情況使用byte[],而對于每個字
占用兩個字節(two bytes per character)的情況則繼續使用char[]。 - 啟用與廢棄:之前可以通過-XX:+UseCompressedStrings選項來啟用這一特性,但它在Java 7中被廢棄,并在Java 8中被完全移除。
Compact Strings(縮小字符串):
- 引入版本:Java 9。
- 特性:Compact Strings是Java 9中引入的一種新機制,用于取代Java 6中的Compressed Strings。它的實現更為徹底,完全使用byte[]來替代char[]存儲字符串數據。同時,為了標識字符串是使用LATIN1編碼還是UTF-16編碼,新引入了一個字段coder。
- 優勢:由于字符串在Java中非常常見,使用byte[]而非char[]可以顯著減少堆內存的使用,這對于那些大量使用字符串的Java應用來說是一個重要的優化。
總結來說,Compressed Strings和Compact Strings都是Java為了優化字符串處理而引入的機制。Compressed Strings在Java 6中引入,但在后續版本中被廢棄;而Compact Strings則在Java 9中引入,作為Compressed Strings的替代方案,它使用byte[]替代char[]來存儲字符串數據,并通過引入新的字段來標識編碼方式,從而實現了更高效的內存使用。