只想把基礎(chǔ)打好-String

下面說一些平時可能不太注意的知識點(diǎn):

  1. String 對象具有只讀特性,所以指向它的任何引用都不可能改變它的值,因此不會其它的引用有什么影響。String的"+"與"+="是java中僅有的兩年重載過的操作符,而java并不允許程序員重載任何操作符。

  2. String的優(yōu)化
    由于String的不可改變的特性,每次改變都會生成一個新的String對象。那如果我們會使用String的重載運(yùn)算符"+"拼接字符串時不是會生成大量的中間對象?java設(shè)計(jì)師一開始也是這樣做的(這也是軟件設(shè)計(jì)中的一個教訓(xùn):除非你用代碼將系統(tǒng)實(shí)現(xiàn),并將它動起來,否則你無法真正了解它會有什么問題),然后他們發(fā)現(xiàn)其性能相當(dāng)糟糕。

public class Concatenation {
    public static void main(String[] args){
    String mango="mango";
    String s="abc"+mango+"def"+45;
    System.out.println(s);
    }
}

然后在class生成目錄下使用javap -c Concatenation

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String mango
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<
init>":()V
      10: ldc           #5                  // String abc
      12: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: aload_1
      16: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: ldc           #7                  // String def
      21: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: bipush        45
      26: invokevirtual #8                  // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
      29: invokevirtual #9                  // Method java/lang/StringBuilder.to
String:()Ljava/lang/String;
      32: astore_2
      33: getstatic     #10                 // Field java/lang/System.out:Ljava/
io/PrintStream;
      36: aload_2
      37: invokevirtual #11                 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
      40: return
}

其中dup與invokevirtural語句相當(dāng)于java虛擬機(jī)上的匯編語言。從上可以看出編譯器自動引用了StringBuilder類,使得那句代碼更高效。但是編譯器為我們優(yōu)化的程序有限。隨時可以用javap來分析你的程序。
當(dāng)你為一個類重寫toString時如果字符串比較簡單那么可以依賴編譯器,否則使用StringBuilder更高效。
3.無意識的遞歸:當(dāng)重寫一個類的的toString的時候,如果你希望打印對象的內(nèi)存地址不要使用this關(guān)鍵字,比如:

@Override
    public String toString() {
        return "*** address:"+this;
    }

當(dāng)調(diào)用this的時候又會調(diào)用這個方法的toString方法,所以在這里我們應(yīng)該使用super.toString()的方法。

  1. String的matches方法可以進(jìn)行正則表達(dá)式判斷:
System.out.println("-3478".matches("-?\\d+"));

輸出結(jié)果:

true

一般說來,比起功能有限的String類,我們更愿意使用Pattern和Matcher對象。

  1. Scanner定界符
    在默認(rèn)情況下,Scanner根據(jù)空白字符對輸入進(jìn)行分詞,但是你可以用正則表達(dá)式指定自己所需的定界符。
public class ScannerDelimiter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("23,5,6,78,23");
        scanner.useDelimiter("\\s*,\\s*");
        while (scanner.hasNext()) {
            System.out.println(scanner.nextInt());
        }
    }
}

運(yùn)行結(jié)果:

23
5
6
78
23

在java引入正則表達(dá)式和Scanner類之前,分割字符串的唯一方法是使用StringTokenier來分詞。不過,現(xiàn)在有了正則表式和Scanner,我們可以使用更加簡單,更加簡潔的方式來完成同樣的工作了。基本上StringTokenizer已經(jīng)棄用了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光劍書架上的書閱讀 4,178評論 2 8
  • 1. Java中的多態(tài)性理解(注意與C++區(qū)分) Java中除了static方法和final方法(private方...
    小敏紙閱讀 1,528評論 0 19
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,627評論 18 399
  • 有關(guān)String的源碼分析,可以查看一下我的前一篇文章:String源碼分析 要理解String的拼接過程,先要理...
    小帝Ele閱讀 901評論 0 2
  • 記得這句話是我高中畢業(yè)留言上寫的,沒想到竟然成了讖語,現(xiàn)如今對我而言,真的應(yīng)驗(yàn)了,我...
    E鍵傾心閱讀 276評論 2 2

友情鏈接更多精彩內(nèi)容