Java基礎之二_字串

IMchg發表於2020-12-23

一 字串建立、判斷相等/為空

1.1 建立字串:雙引號與new

引號和new建立的區別:https://www.cnblogs.com/wdfordream/p/9449710.html

字串物件的建立很特殊,除了像一般物件那樣通過new建立物件外,還能用雙引號直接為字串引用變數指定字串物件的值。其實,考慮到字面值常量的概念,雙引號的字串內容其實也可以理解為一個引用(變數),只不過這個引用(變數)的名稱和其指向的物件代表的值一樣。如例子所示,雙引號字串可以像引用變數一樣直接呼叫字串類的方法,可見其確實是一個引用(變數)

        System.out.println("abc".length());		// 3

引號建立,意味著在是在程式中寫死的,在程式執行之前其對應的字串物件就是確定的了。引號建立的字串物件就是常量,會在程式載入時建立(猜的),而且被存放到JVM維護的字串例項池

new建立,則字串物件是在程式執行時建立的,和普通物件一樣,儲存在中。

引號建立時,JVM會先在字串例項池中是否已存在,如果已存在直接返回地址,不重複建立,所以多次建立實際為同一個物件new建立時,總是會在堆中開闢新的記憶體區域,多次建立為不同物件。引號建立和new建立的字串物件所在的記憶體區域都不同,二者自然不是同一個物件。

連結中部落格說:new建立字串物件時,也會先在字串例項池中查詢,如果沒有,也會同時在字串例項池中建立。那麼下面這種情況也是嗎?

		String str1 = "abc";
        String str2 = str1.substring(0,1);
        System.out.println(str2);

str2也會在字串例項池中建立嗎?

總結:
在Java中與字串相關的記憶體區域有三個:字串例項池、堆、棧。程式碼中用雙引號寫明的字串物件都存放在字串例項池,new建立的字串物件放在堆,字串物件的引用放在棧。

補充:

Java字面值常量:https://blog.csdn.net/qq_36756682/article/details/102664502

  1. 考慮到字面值常量概念,那字串物件存在的兩種建立方式、判斷值相等得用equals等問題其實也不算特殊。因為所有內建型別都存在字面值常量,所以其他內建物件也存在一樣的問題,如下面例子所示。
  2. 之所以對其他內建型別感覺沒這麼明顯,是因為:從理解上看,String對標的應該是Integer、Character這些物件;但在操作上,Java中為這些內建資料型別提供了其他關鍵字,如:int、char,所以Integer、Character就用的少了,問題就不突出了。但是字串對應的只有String一個關鍵字。【int型別其實比String更復雜,具體見下面例子】
  3. 判斷Integer物件的值是否相等使用的依然是equals(),可見equals相當重要。equals可是從Object中繼承的方法。
  4. 字面值常量:1、2、‘a’、‘b’…儲存在哪?常量池,具體參考以下博文:

https://blog.csdn.net/mrdmmm/article/details/89484474
https://blog.csdn.net/chenkaibsw/article/details/80848069

        Integer i = new Integer(1);
        Integer i1 = 1;

        Character ch = new Character('a');
        Character ch1 = 'a';

        String str = new String("abc");
        String str1 = "abc";

        System.out.println(i==i1);				// false
        System.out.println(ch==ch1);			// false
        System.out.println(str==str1);			// false

        System.out.println(i.equals(i1));		// true
        System.out.println(ch.equals(ch1));		// true
        System.out.println(str.equals(str1));	// true

再補充一個int的例子,這才叫跌破眼鏡

        Integer i = new Integer(1);
        Integer j = 1;
        int k =1;

        System.out.println(i==j);	// false
        System.out.println(i==k);	// true
        System.out.println(j==k);	// true

1. 注意看,i和j不等,這在上面已經分析過了;但是二者竟然都能和k相等;注意看,是物件相等。
2. 換句話說:k==i、k==j,推不出i==j,怎麼解釋?
3. 個人理解這是操作符過載,==操作符在涉及intchar...時,不再表示物件相等,而是表示值相等。
4. 可見基本資料型別intchar等真是極其特殊,只用考慮值,不做物件考慮。
5. int i=1int j=3-2,是等價的,沒有區別,Integer i=1 和 Integer j=3-2,也是等價的,是同一個物件

1.2 字串物件判斷相等/為空:

字串判斷相等/為空這種說法本身是不明確的,應該說判斷:字串物件值相等、字串物件相等、字串物件值為空、字串物件為空。

等號運算子"==",用於判斷物件相等,即同一塊記憶體單元。equals()方法,用於判斷物件的值相等,所有類都存在equals方法(繼承自Object)。

判斷字串物件相等:==
        String str1 = "abc";
        String str2 = "abc";
        System.out.println(str1 == str2);		// true
        
判斷字串物件值相等:equals
        String str1 = "abc";
        String str2 = new String("abc");
        System.out.println(str1.equals(str2));	// true

判斷字串物件為空:== null
【注意null物件也能進行== 運算】
		String str1 = null;
        System.out.println(str1==null);			// true
        
判斷字串物件值為空: equals("")length()==0
【確定字串物件不為null的情況下才能按以下寫法】
		String str1 = "";
        System.out.println(str1.equals(""));
        System.out.println(str1.length()==0);
【不確定是否為null,更穩妥的寫法如下:】
		String str1 = "";
        System.out.println("".equals(str1));	// true
        System.out.println(str1!==null && str1.length()==0); // true

綜上所述:
1.與字串物件本身相關的判斷,都用==,且只能用==
2.與字串物件值相關的判斷,都用equals(),判斷值為空也可以使用length()

補充:
什麼叫物件為空?什麼叫物件沒有初始化?有什麼區別?

  1. 物件為空並不是說物件沒有值,而是說物件為空值,也即物件的值為null。這個null值,可以是手動賦的,也可以是第三方函式的返回結果,也可能是靜態變數由JVM預設初始化的。
  2. 物件沒有初始化說的是物件沒有值,區域性變數定義後沒有賦初值就會出現這個問題。
  3. 呼叫沒有初始化的物件是編譯時問題,在IDE中就會報紅;呼叫為空值的物件是執行時的問題,程式執行時才會報錯。【空指標異常】

二 字串常量和字串變數

字串變數變數的說法是錯誤的,應該叫字串緩衝變數,為了好記,將錯就錯

2.1 String、StringBuffer、StringBuilder的區別

https://blog.csdn.net/csxypr/article/details/92378336
https://blog.csdn.net/fzy198926/article/details/88792365

  1. String變數不應該叫字串物件,而應該叫字串物件的引用變數。實際上,建立任意物件時,都不應該把XXX叫做XXX物件,而應該叫做XXX物件的引用變數。物件存放在堆,引用變數存放在棧。
  2. 字串物件(不是指引用變數)是一個常量,一旦建立值就不能改變,也就是所對應的記憶體單元的值不能改變,長時間不使用,會被垃圾回收;
  3. 對字串物件的各種改變實際上是建立了新的字串物件,分配了新的記憶體單元,並讓原來的引用變數指向這個新的字串物件。

根據上面的敘述,顯而易見,程式中要頻繁修改字串物件的值時,使用字串物件是很不利的。此時,應該使用字串緩衝物件StringBuffer、StringBuilder,這兩個(指向的物件)是可變的,不會產生新的物件,可在修改完成後再轉為String物件。【不僅比String佔記憶體小,執行的也更快】

StringBuffer和StringBuilder的區別在於:
二者方法和功能完全是等價的,區別在於:StringBuffer是執行緒安全的,有同步機制;StringBuilder不是執行緒安全的,但因此更快。單執行緒時優先使用StringBuilder,多執行緒時使用StringBuffer。

2.2 StringBuffer、StringBuilder

https://www.runoob.com/java/java-stringbuffer.html

二者API一致,且訪問物件的操作與String物件也類似,主要是使用修改操作,包括:append、insert、delete、replace、reverse

        StringBuilder stringBuilder = new StringBuilder("123");
        stringBuilder.append("456");		// 123456
        stringBuilder.insert(0,"abc");		// abc123456
        stringBuilder.delete(0,2);			// c123456
        stringBuilder.replace(0,1,"xyz");	// xyz123456
        stringBuilder.reverse();			// 654321zyx
        System.out.println(stringBuilder.toString());

注意:
String類沒有reverse方法,StringBuilder才有。在字串表示大數時,可能涉及reverse操作,因為數值高位在左邊,而陣列高位在右邊。

三 字串常用操作

3.1 字串與字元陣列轉換

String s = "123";
char[] chars = s.toCharArray();
String str = String.valueOf(chars);

注意:
若用字串表示數值,在轉為字元陣列時要特別注意,數值高位在陣列低位

3.2 字串擷取

四 正規表示式

相關文章