String字符串,,是一種引用數(shù)據(jù)類型,并不是基礎(chǔ)數(shù)據(jù)類型,。 對于基礎(chǔ)數(shù)據(jù)類型和引用數(shù)據(jù)類型的區(qū)別: 基礎(chǔ)數(shù)據(jù)類型,,在創(chuàng)建時直接將值存放在棧內(nèi)存中。 引用數(shù)據(jù)類型,,在創(chuàng)建時棧內(nèi)存中存放一個引用,,這個引用存放的是堆內(nèi)存的位置,而堆內(nèi)存中就是存放具體的值,。 舉例說明: 假如String對象是一個儲物柜,,在使用儲物柜時(相當(dāng)于新建一個String對象), 我們需要會得到一張記著儲物柜的小票(小票相當(dāng)于棧內(nèi)存空間,,小票上保存引用),, 憑借這張小票就可以找到儲物柜,然后拿到儲物柜中存放的東西(儲物柜相當(dāng)于堆內(nèi)存空間,,可以根據(jù)引用去得到堆內(nèi)存中的值),。 對于基礎(chǔ)數(shù)據(jù)類型,則是直接將值寫在小票上,。 String的底層數(shù)據(jù)結(jié)構(gòu)String的底層實現(xiàn)是字符數(shù)組,,這一點可以在源碼中看到, 其中屬性 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 進行修飾,,既然是常量。 在發(fā)生對象需要重新賦值的時候,,String的做法是,,將String對象的棧內(nèi)存與堆內(nèi)存的引用斷開。 再將棧內(nèi)存中的引用指向新的堆內(nèi)存空間,。 本質(zhì)上就是新建一個String對象,。 由此可以引發(fā)一個問題,如果代碼中頻繁出現(xiàn)對String對象的重新賦值意味著會有大量的堆內(nèi)存被棄用,。 這部分被棄用的堆內(nèi)存空間只能通過垃圾回收機制進行回收,,這會降低內(nèi)存的利用率。(浪費內(nèi)存是一方面,,另一方面垃圾回收也會耗費資源,。此問題在面試中出現(xiàn)的概率比較高) 這個問題可以通過使用StringBuffer或者StringBuilder來解決(StringBuffer和StringBuilder會在接下來的文章進行介紹)。 以下是《Java開發(fā)實戰(zhàn)經(jīng)典》一書中的示例: String對象的比較比較方式分為兩種(自定義比較方法除外): a.雙等號(==):雙等號的判斷依據(jù)是對象的堆內(nèi)存地址是否相同,。(用上面儲物柜的例子就是同一個儲物柜,,當(dāng)然放的是同樣的東西) 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循環(huán)比較字符數(shù)組中的值 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關(guān)鍵詞創(chuàng)建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)); } } 控制臺結(jié)果: str1 == str2: true str1 equals str2: true str1 == str3: false str1 equals str3: true str1 == str4: false 通過 str1 == str2: true 結(jié)果得出的結(jié)論: String類在不使用new 關(guān)鍵詞來新建對象時,,如果str1 和 str2 的取值相同,, 并不會為str1 和 str2 分別開辟堆內(nèi)存空間,而是將str1 和 str2同時指向同一個堆內(nèi)存,,減少內(nèi)存浪費,。 String類常用方法以下是《Java開發(fā)實戰(zhàn)經(jīng)典》一書中表格: 結(jié)語紙上得來終覺淺,,絕知此事要躬行。 String類中的內(nèi)容很多,,單構(gòu)造方法就是十多種,。 雖然內(nèi)容多,但是難度都不高可能花看一個小視頻的時間能看完,。 這里對String類進行簡單的介紹,。 來源:http://www./content-4-176451.html |
|