String類的疑惑,String類疑惑

來源:互聯網
上載者:User

String類的疑惑,String類疑惑

Java String類的疑惑:

  • 建立
  • 拼接

String是java的常用類之一,本質是字元數組char[]。String類是final類,不可被繼承。關於String的建立,可以通過new來建立對象,也可以直接賦值。但是這兩種建立方式的實現機制是不同的。提到對象的建立,我們就會想到堆、棧,這裡還有一個string pool的概念,JVM維護一個String池,池中的string對象不可重複,string池不屬於堆棧,而是一個常量池。

一、建立

建立一個String對象,主要有兩種方式:

String str1 = new String("abc"); //在string池中建立abc對象,在堆中建立abc對象,棧中的str1指向該對象String str2 = "abc";//在string池中尋找abc對象,已存在,直接將棧中的str2指向該對象
仔細看兩行注釋,執行完第一行代碼後,記憶體

執行完第二行代碼,記憶體

可通過記憶體比較來驗證:

先自己思考一下結果再往下繼續啦!

String str1 = "abc";String str2 = "abc";String str3 = new String("abc");System.out.println(str1 == str2); System.out.println(str1 ==str3); System.out.println(str1 == "abc"); System.out.println(str3 =="abc"); System.out.println(str1 == str3.intern());System.out.println(str3 == str3.intern());
運行結果:


解析:

==比較的是記憶體位址,

str1==str2;// 都指向string池中的對象,所以返回true

str1==str3;//str1指向string池中的對象,str3指向堆中對象,所以,返回false

str1==“abc”; //都指向string池中的對象,所以返回true

str3==”abc“;//str3指向堆記憶體對象,另一個是string池中的對象,所以,返回false

str1==str3.intern(); //都指向string池中的對象,返回true

str3==str3.intern();//str3指向堆記憶體對象,str3.intern()指向string池中的對象,所以,返回false

intern()方法是返回字串對象的正常化表示形式,也就是說當調用intern()時,如果string池中已經包含一個等於(equals)此string對象的字串,則返回池中的字串。

二、拼接

先來思考一下執行結果:

<span style="white-space:pre"></span>String hello = "hello";String hel = "hel";String lo = "lo";System.out.println(hello == "hel"+"lo");System.out.println(hello == "hel"+"looo");System.out.println(hello== "hel" + lo);
運行結果:

解析:

  • 如果+串連的都是常量時,先判斷string池中有沒有hello,如果存在,直接返回其地址,不再重新建立。
  • 如果+串連的有物件類型時,則直接在堆中產生一個新對象。

關於String拼接的繼續思考:

        由於String類是final的,也就是對象一旦建立,就不能改變其內在狀態了,但是,拼接操作是要改變String的內部狀態的,在這種矛盾下,要維護string的非可變性,只好在拼接完成後再建立一個新的String對象,也就是說,每執行一次拼接操作,都會產生新對象的產生。當大量指向拼接操作時,就會導致大量對象的建立,這樣,就產生了效能問題。

       為瞭解決這個問題,jkd為string類提供了一個可變的配套類StringBuffer。由於StringBuffer是可變的,拼接時僅僅是改變了內部資料結構,而不會建立新對象,因此,效能上有很大的提高。


一個類的定義中,含有string類型情況怎實現

string是參考型別,但它也有一些實值型別的特徵。

String傳值還是傳引用
C#的String聲明是class String,當然是傳引用。
不過,之所以有這個疑惑,多數是因為這個情況:
string a = "aaa";
string b = a;
b = "bbb";
或者是這麼幾行代碼:
public void Swap(string s1, string s2)
{
string temp=s1;
s1=s2;
s2=temp;
}
這時候結果一列印,結果發現a的值還沒有變,Swap也沒有成功,這時候就會有幻覺:是不是沒有傳引用啊?
呵呵,string不會這麼粗暴的打亂“聲明為class就是傳引用”這種規則的。
分析一下:
string a = "aaa"; //==> a----->new String("aaa")
string b = a; //==> b----->a, 傳引用
b = "bbb"; //==> b----->new String("bbb"), 傳引用,b指向了一個新的字串,a並沒有變。

Swap函數也是這樣,比如說傳了a, b進去(a="aaa", b="bbb"),
//s1----->a, s2----->b
string temp=s1;//temp----->s1----->a
s1=s2; //s1----->s2----->b;
s2=temp; //s2----->temp----->a
結果是,s1和s2確實是Swap了,但是這種結果並不會影響到a和b
 
C#中string類型是什類型

string是參考型別,但它也有一些實值型別的特徵。

String傳值還是傳引用
C#的String聲明是class String,當然是傳引用。
不過,之所以有這個疑惑,多數是因為這個情況:
string a = "aaa";
string b = a;
b = "bbb";
或者是這麼幾行代碼:
public void Swap(string s1, string s2)
{
string temp=s1;
s1=s2;
s2=temp;
}
這時候結果一列印,結果發現a的值還沒有變,Swap也沒有成功,這時候就會有幻覺:是不是沒有傳引用啊?
呵呵,string不會這麼粗暴的打亂“聲明為class就是傳引用”這種規則的。
分析一下:
string a = "aaa"; //==> a----->new String("aaa")
string b = a; //==> b----->a, 傳引用
b = "bbb"; //==> b----->new String("bbb"), 傳引用,b指向了一個新的字串,a並沒有變。

Swap函數也是這樣,比如說傳了a, b進去(a="aaa", b="bbb"),
//s1----->a, s2----->b
string temp=s1;//temp----->s1----->a
s1=s2; //s1----->s2----->b;
s2=temp; //s2----->temp----->a
結果是,s1和s2確實是Swap了,但是這種結果並不會影響到a和b
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.