String 字符串對象


String是什么

String字符串,是一種引用數據類型,並不是基礎數據類型。

對於基礎數據類型和引用數據類型的區別:

基礎數據類型,在創建時直接將值存放在棧內存中。

引用數據類型,在創建時棧內存中存放一個引用,這個引用存放的是堆內存的位置,而堆內存中就是存放具體的值。

舉例說明:

假如String對象是一個儲物櫃,在使用儲物櫃時(相當於新建一個String對象),

我們需要會得到一張記着儲物櫃的小票(小票相當於棧內存空間,小票上保存引用),

憑借這張小票就可以找到儲物櫃,然后拿到儲物櫃中存放的東西(儲物櫃相當於堆內存空間,可以根據引用去得到堆內存中的值)。

對於基礎數據類型,則是直接將值寫在小票上。

String的底層數據結構

String的底層實現是字符數組,這一點可以在源碼中看到,

其中屬性 private final char value[]; 就是用來存儲String的值,

以下是String類的部分源碼:

 1 public final class String
 2     implements java.io.Serializable, Comparable<String>, CharSequence {
 3     /** The value is used for character storage. */
 4     private final char value[];
 5 
 6     /** Cache the hash code for the string */
 7     private int hash; // Default to 0
 8 
 9     /** use serialVersionUID from JDK 1.0.2 for interoperability */
10     private static final long serialVersionUID = -6849794470754667710L;

String類被final修飾,則表示String類不可以被繼承。

String類的value屬性使用了 final 進行修飾,則表示value是一個常量,常量不可以更改。

String對象的重新賦值

String類的源碼中可以看到String類的value屬性使用了 final 進行修飾,既然是常量。

在發生對象需要重新賦值的時候,String的做法是,將String對象的棧內存與堆內存的引用斷開。

再將棧內存中的引用指向新的堆內存空間。

本質上就是新建一個String對象。

由此可以引發一個問題,如果代碼中頻繁出現對String對象的重新賦值意味着會有大量的堆內存被棄用。

這部分被棄用的堆內存空間只能通過垃圾回收機制進行回收,這會降低內存的利用率。(浪費內存是一方面,另一方面垃圾回收也會耗費資源。此問題在面試中出現的概率比較高)

這個問題可以通過使用StringBuffer或者StringBuilder來解決(StringBuffer和StringBuilder會在接下來的文章進行介紹)。

以下是《Java開發實戰經典》一書中的示例:

 

String對象的比較

比較方式分為兩種(自定義比較方法除外):

a.雙等號(==):雙等號的判斷依據是對象的堆內存地址是否相同。(用上面儲物櫃的例子就是同一個儲物櫃,當然放的是同樣的東西)

b.使用方法equals(Object anObject):方法比較的是對象的取值。

String類中equals(Object anObject)方法源碼:

 1     public boolean equals(Object anObject) {
 2         if (this == anObject) {
 3             return true;
 4         }
 5         if (anObject instanceof String) {
 6             String anotherString = (String)anObject;
 7             int n = value.length;
 8             if (n == anotherString.value.length) {
 9                 char v1[] = value;
10                 char v2[] = anotherString.value;
11                 int i = 0;
12                 while (n-- != 0) {               //通過while循環比較字符數組中的值
13                     if (v1[i] != v2[i])
14                         return false;
15                     i++;
16                 }
17                 return true;
18             }
19         }
20         return false;
21     }

 

以下是代碼示例:

public class TestString {
    public static void main(String[] args) {
        String str1 = "a";
        String str2 = "a";
        String str3 = new String("a");   //使用new關鍵詞創建String對象
        String str4 = "b";
        
        System.out.println("str1  ==    str2: "+(str1 == str2));
        System.out.println("str1 equals str2: "+(str1.equals(str2)));
        System.out.println("str1  ==    str3: "+(str1 == str3));
        System.out.println("str1 equals str3: "+(str1.equals(str3)));
        System.out.println("str1  ==    str4: "+(str1 == str4));
    }
}

 

控制台結果:

str1  ==    str2: true
str1 equals str2: true
str1  ==    str3: false
str1 equals str3: true
str1  ==    str4: false

通過 str1 == str2: true 結果得出的結論:

String類在不使用new 關鍵詞來新建對象時,如果str1 和 str2 的取值相同,

並不會為str1 和 str2 分別開辟堆內存空間,而是將str1 和 str2同時指向同一個堆內存,減少內存浪費。

String類常用方法

以下是《Java開發實戰經典》一書中表格:

 

 

結語

紙上得來終覺淺,絕知此事要躬行。

String類中的內容很多,單構造方法就是十多種。

雖然內容多,但是難度都不高可能花看一個小視頻的時間能看完。

這里對String類進行簡單的介紹。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM