天天看點

【重識Java】一文弄清Java字元串易混易錯點

本文主要介紹一些關于Java字元串的易錯易忘的知識點,并非系統完整介紹,如有在意,還請見諒。

一、字元串的概念

1.字元串到底是什麼

💭:字元串的概念有什麼好說的?😪

💬:這裡不是的簡單重複其一般性概念哦,而是專門指明Java中字元串的本質

在Java中,其實Java字元串就是Unicode字元序列。String 并不是Java内置的基本類型,而是由标準Java類庫中提供的一個預定義類。

2.差別 碼點 和 代碼單元

🔔概念解釋:

碼點是指 一個編碼表 中的 某個字元 對應的 代碼值。

Unicode的碼點分為17個代碼級别,第一個級别是基本的多語言級别,碼點從U+0000——U+FFFF,其餘的16個級别從U+10000——U+10FFFF,其中包括一些輔助字元。

代碼單元則是指在基本的多語言級别中,每個字元用16位表示代碼單元。而輔助字元則采用一對連續的代碼單元進行編碼。

總之,一個碼點既可以表示一個一般字元也可以表示一個輔助字元;而一個代碼單元則隻能表示一個一般字元,要兩個代碼單元才能表示一個輔助字元。

🚬 我的個人了解是:代碼單元其實是一種抽象的機關1,為了友善周遊字元串中的一般字元和表示char類型字元的。

⭕️補充:如果想要了解更多關于編碼的細節問題請看:

​編碼格式簡介(ANSI、GBK、GB2312、UTF-8、GB18030和 UNICODE)

二、字元串的有趣方法

1.像切片一樣擷取子串

用過Python的應該知道Python有一個好用的處理字元串的方式叫做 切片,而在Java中同樣有類似方法,并且規律相同,都是左閉右開。

🕑方法如下:

【重識Java】一文弄清Java字元串易混易錯點

🕒代碼實作如下:

【重識Java】一文弄清Java字元串易混易錯點

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

⭕️補充:從以上結果可以看出,substring(m,n) 方法------當m與n相等時,截取到的子串為空,并不會報錯

2.拼接字元串

🔔解釋:

在Java中,當一個字元串與一個非字元串的值進行拼接時,後者會被轉換為字元串(其實任何一個Java對象都能轉換為字元串,重寫toString方法即可)而使用 + (加号)就可以拼接啦。

⭕️補充:在拼接多個字元串時,如果想要用一個界定符分隔它們,則可以使用String類的 靜态join 方法

🕑方法如下:

【重識Java】一文弄清Java字元串易混易錯點

🕒代碼實作如下:

【重識Java】一文弄清Java字元串易混易錯點

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

3.處理碼點和代碼單元

經常使用的是擷取代碼單元,因為擷取到代碼單元經常與char字元進行比較或者其他處理,本文最後會給出一道算法題,其中就可以利用這個。

3.1擷取長度

🕒代碼實作如下:

public class Article {
    public static void main(String[] args) {
        String str = "hi\uD835\uDD46"; //hi後面的其實是輔助字元:𝕆
        //擷取字元串的代碼單元長度
        int unit_len = str.length();
        //擷取字元串的碼點長度/碼點數量
        int cpCount = str.codePointCount(0,unit_len);
        System.out.println("代碼單元長度:"+unit_len);
        System.out.println("碼點長度/數量:"+cpCount);
    }
}      

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

怎麼樣,是不是很有趣?😄

3.2擷取索引為n處的值

🕒代碼實作如下:

public class Article {
    public static void main(String[] args) {
        String str = "hi\uD835\uDD46";
        //擷取索引為1處的代碼單元
        char first = str.charAt(1);
        //擷取索引為1處的碼點
        int cp = str.codePointAt(1);   
        //有意思的是碼點長度為3,但卻可以取到索引3處的值;這是為什麼呢?
        System.out.println("代碼單元:"+first);
        System.out.println("碼點:"+cp);
    }
}      

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

4.将字元串轉為字元數組

🕑方法如下:

【重識Java】一文弄清Java字元串易混易錯點

🕒代碼實作如下:

public class Article {
    public static void main(String[] args) {
        String str = "hi,windx";
        char[] c = str.toCharArray();
        for (int i = 0; i < c.length; i++) {
            System.out.print(c[i]+" ");
        }
    }
}      

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

5.其它方法(判别前字尾、去除空白符)

5.1 判别前字尾

有時我們通常會對一個字元串的字首或字尾進行判斷,看是否滿足篩選條件,此時這個方法就能夠派上用處了(如果用substring()的話有時會有意想不到的Bug)。

🕑方法如下:

①字首:

【重識Java】一文弄清Java字元串易混易錯點

②字尾:

【重識Java】一文弄清Java字元串易混易錯點

分别判斷是否以某字元串開頭、以某字元串結尾,均傳回boolean類型值。

5.2 去除空白符

該方法可以删除原始字元串頭部和尾部小于等于U+0020的字元或空格,同樣用于對字元串進行處理。

🕑方法如下:

【重識Java】一文弄清Java字元串易混易錯點

三、判斷字元串是否相等

👉 首先要注意的是字元串是不可變的,當簡單複制一個字元串時,其實是共享了同一處空間,隻是複制了引用而已。

是以,

  • 使用 == 運算符判斷兩字元串是否相等,比較的隻是兩字元串的位址。
  • 如果要比較内容,需要使用equals()方法!而不區分大小寫比較,則使用equalsIgnoreCase()方法。

⭕️補充:不論是使用 + 連接配接空字元串還是substring()擷取子串或者進行大小寫轉換,都會改變字元串的位址

🕒代碼測試如下:

public static void main(String[] args) {
        String a = "aaa";
        String b = a;
        System.out.println("初始a的位址:");
        System.out.println("a:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(a)));
        a+="";
        if(b==a){
            System.out.println("b==a");
        }
        if(b.equals(a)){
            System.out.println("b.equals(a)");
        }
        System.out.println("與空串拼接後a的位址:");
        System.out.println("a:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(a)));
        System.out.println("b的位址:");
        System.out.println("b:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(b)));
    }      

🕓代碼運作結果如下:

【重識Java】一文弄清Java字元串易混易錯點

可以看到由初始的a字元串複制的b字元串的位址與其初始位址是相等的,而a在拼接空串後,其位址發生了變化,但内容值不變。