第十三章、字符串
13.1 不可變字符串
String對象是不可變的(Thread-Safe): 線程安全的。
String s = "abc" + "def" + 4.7 ;
String類中每個(gè)看起來會修改String值的方法,實(shí)際上都是創(chuàng)建了一個(gè)全新的String對象,以包含修改后的字符串內(nèi)容。而最初的String對象則絲毫未動。
13.2 重載“+”與 StringBuilder.append()
用于String的“+”與“+=”是Java中僅有的兩個(gè)重載過的運(yùn)算符,Java不允許程序員重載任何運(yùn)算符(但其實(shí)Java語言比C++更容易實(shí)現(xiàn)運(yùn)算符的重載)。
String的不可變性帶來了一定的效率問題,比如String的“+”運(yùn)算,每“+”一次都會生成一個(gè)新的String對象(內(nèi)存垃圾)。
Java編譯器(javac)一般會自動優(yōu)化,但不同情況下,優(yōu)化的程度不夠。
13.3 無意識的遞歸
由String對象后面跟著一個(gè)“+”,再后面的對象不是String時(shí),編譯器會使后面的對象通過toString()自動類型轉(zhuǎn)換成String.
如果這發(fā)生在自定義的類的重寫的toString()方法體內(nèi),就有可能發(fā)生無限遞歸,運(yùn)行時(shí)拋出java.lang.StackOverflowError棧溢出異常。
// InfiniteRecursion.java
public class InfiniteRecursion{
? ? public String toString(){
? ? ? ? //應(yīng)該調(diào)用Object.toString()方法,所以此處應(yīng)為super.toString()。
? ? ? ? return " InfiniteRecursion address: " + this + "\n";? //此處會遞歸調(diào)用toString(),出現(xiàn)異常。
? ? }
? ? public static void main(String[] args){
? ? ? ? List<InfiniteRecursion> v = new ArrayList<InfiniteRecursion>();
? ? ? ? for(int i = 0; i < 10; i++)
? ? ? ? ? ? v.add(new InfiniteRecursion());
? ? ? ? System.out.println(v);
? ? }
}
13.4 格式化輸出
a. System.out.format("Row [%d %f]", x, y);
b. Formatter類:Formatter.format();
13.5 正則表達(dá)式
a. 強(qiáng)大&靈活的文本處理工具;
b. 使用編程方式,構(gòu)造復(fù)雜的文本模式;
作用: 可實(shí)現(xiàn):匹配&選擇&編輯&驗(yàn)證String。
13.5.1 語法(Pattern&Matcher)
Pattern p = Pattern.compile(arg);
Matcher m = p.matcher(arg[0]); //判斷輸入的String 是否滿足正則表達(dá)式
13.6 String StringBuilder StringBuffer區(qū)別
a. String: Java 提供了?String 類來創(chuàng)建和操作字符串。
b. StringBuffer 和 StringBuilder:
當(dāng)對字符串進(jìn)行修改的時(shí)候,需要使用?StringBuffer 和 StringBuilder 類。
c. StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問)。
d. 由于?StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用?StringBuilder 類。然而在應(yīng)用程序要求線程安全的情況下,則必須使用?StringBuffer 類。
13.7 Scanner & StringTokenize
Scanner定界符:為Java SE1.5 新增
StringTokenize:廢棄使用!