天天看點

【Java紮馬步】String不得不明白的3個點

我也可以證明,要想學好Java程式設計,必須得把String的馬步給紮得穩穩的。之前,我自以為有了幾年程式設計經驗,覺得String這些老生常談的話題(比如equals與==)可真是無聊!但事實并非如此,這些基礎知識需要反複的傳播和推廣!

請允許我先舉一個例子(請勿對号入座):

有小夥伴在沉默王二技術交流群裡發了下面這樣一幅圖檔,問:“我這樣判斷字元串為空 正确嗎?”

我沒敢輕易下結論,仔仔細細的看了好一遍;先判null,之後把entName放在equals的參數位置判空,我覺得這位小夥的代碼寫得很完美啊。

但意想不到的是,小夥伴緊接着說:“但是我調試,是null的時候還是進入if ”。

我當時回答說:“那你的調試肯定是瞎調,或者見鬼了。嘿嘿”

我當時詫異極了。幸好之後小夥伴發來debug的截圖!

你說呢,這樣寫不報錯才怪!

之後我稍解釋了一番,并回複說:“建議啊,不是我打擊啊,還是多紮紮馬步比較好”。

下面我們就細緻來說一下String不得不明白的3個點。

1、檢查String是否相等

如上文提到的,檢查String是否相等最好要使用equals方法,盡量少使用==操作符。

String cmower ="cmower";

System.out.println("cmower" == cmower);//true

System.out.println("cmower".equals(cmower));//true

System.out.println("cmower".substring(0, 3) == "cmo");//false

System.out.println("cmower".substring(0, 3).equals("cmo"));//true

==操作符确定的是兩個String是否放在同一個位置上。

“cmower”字元串和cmower變量指向的引用就是在同一個位置上,是以==比較結果為true。

在Java虛拟機上,隻有字元串常量是共享的(”cmower”字元串和cmower變量共享了同一個位址)。但是對于substring産生的結果就不共享了。

對于equals,比較的則是兩個對象是否具有相同的字元集。

Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

2、String不可變

public static void main(String[] args) {

   String s = "s";

   String ss = toUpper(s);

   System.out.println(s);//s

   System.out.println(ss);//S

}

private static String toUpper(String b) {

   String bb = b.toUpperCase();

   System.out.println(b);//s

   return bb;

“s”是一個字元串對象,你怎麼也不能把這個對象變成“S”。也就是說小s和大S盡管是雙胞胎,但她們倆注定都不能成為對方。

3、+與StringBuilder

首先,我們先來看對于+操作符,在Java虛拟機下是如何工作的。

public static String add1() {

   String b = "b";

   String s = "a" + b + "c" + "d" + 100;

   return s;

public static String add2() {

   String s = "a" + "b" + "c" + "d" + 100;

對于add1和add2方法,你認為Java虛拟機的工作方式一樣嗎?

閉上眼睛10秒鐘,先想一會。

我們來揭曉答案:

差别是不是很大?

這說明,+操作符在拼接String時,會根據情況做一定的選擇。比如add1方法,Java會new 一個StringBuilder對象,來對abcd100進行append操作,之後再toString出來。

那麼也就說,Java會自動會為我們優化代碼,以後我們盡管使用+操作符就行了。但事實并非如此,再來看一串代碼。

public static String plus() {

   String result = "";

   for (int i = 0; i < 10; i++) {

       result += "a";

   }

   return result;

public static String sb() {

   StringBuilder sb = new StringBuilder();

       sb.append("a");

   return sb.toString();

這個時候,你選擇用sb方法還是plus方法?

再閉上眼睛10秒鐘,想一下你的答案。

javap執行結果如下:

看得出plus方法的8-34行是一個循環,11行時建立了StringBuilder對象,也就是在循環内。這個方法執行了10次,那麼也就建立了10個StringBuilder對象。

再來看sb方法的結果:

顯而易見,StringBuilder對象隻有一個。

在使用StringBuilder時,盡量少“在append方法的參數中使用+操作符”:

public static String sb1() {

       sb.append("a" + b);

這樣做糟糕至極:

“a” + b時又重新建立了StringBuilder對象。

總結如下,

1. 在進行循環多次拼接String時,用StringBuilder而不用+操作符!

2. +操作符隻用于少量字元串變量拼接,在記憶體中操作,性能更高!

3. append方法的參數少用+操作符!

最後,留一個話題讨論一下。

對于substring(int beginIndex, int endIndex)方法,在《Java核心技術卷1》上說,endIndex指的是不想複制的第一個位置。但這句話很拗口。我自己也經常搞不清楚到底endIndex該為多少,總是怕搞錯,最後非要輸出結果确認一下!

問:“如何更好的确定endIndex?”

"cmower".substring(0, 3);