字符串

String類

  • String s1 = "abc"; //在常量區(qū)中存放了一個"abc"的字符串對象

      String s2 = "abc";//s2引用常量區(qū)中的對象,因此不會創(chuàng)建新的對象。
    
      String s3 = new String("abc");//在堆中創(chuàng)建新的對象
    
      String s4 = new String("abc");//在堆中又創(chuàng)建一個新的對象
    
  • String,StringBuffer與StringBuilder的區(qū)別??

String 字符串常量
StringBuffer 字符串變量(線程安全)
StringBuilder 字符串變量(非線程安全)

  • 關(guān)于String類。
    1、String類時final類,所以是不可繼承的;
    2、String類是的本質(zhì)是字符數(shù)組char[];
    3、Java運(yùn)行時會維護(hù)一個String Pool(String池),JavaDoc翻譯很模糊“字符串緩沖區(qū)”。String池用來存放運(yùn)行時中產(chǎn) 生的各種字符串,并且池中的字符串的內(nèi)容不重復(fù)。而一般對象不存在這個緩沖池,并且創(chuàng)建的對象僅僅存在于方法的堆 棧區(qū)。

    String 類型和 StringBuffer 類型的主要性能區(qū)別其實(shí)在于 String 是不可變的對象, 因此在每次對 String 類型進(jìn)行改變的時候其實(shí)都等同于生成了一個新的 String 對象,然后將指針指向新的 String 對象,所以經(jīng)常改變內(nèi)容的字符串最好不要用 String ,因?yàn)槊看紊蓪ο蠖紩ο到y(tǒng)性能產(chǎn)生影響,特別當(dāng)內(nèi)存中無引用對象多了以后, JVM 的 GC 就會開始工作,那速度是一定會相當(dāng)慢的。
     而如果是使用 StringBuffer 類則結(jié)果就不一樣了,每次結(jié)果都會對 StringBuffer 對象本身進(jìn)行操作,而不是生成新的對象,再改變對象引用。所以在一般情況下我們推薦使用 StringBuffer ,特別是字符串對象經(jīng)常改變的情況下。
    
    在某些特別情況下, String 對象的字符串拼接其實(shí)是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度并不會比 StringBuffer 對象慢,而特別是以下的字符串對象生成中, String 效率是遠(yuǎn)要StringBuffer 快的:
    
  • 關(guān)于String S1 = “This is only a” + “ simple” + “ test”;的簡介;

StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你會很驚訝的發(fā)現(xiàn),生成 String S1 對象的速度簡直太快了,而這個時候 StringBuffer 居然速度上根本一點(diǎn)都不占優(yōu)勢。其實(shí)這是 JVM 的一個把戲,在 JVM 眼里,這個
String S1 = “This is only a” + “ simple” + “test”; 其實(shí)就是:
String S1 = “This is only a simple test”; 所以當(dāng)然不需要太多的時間了。

StringBuilder一個可變的字符序列是5.0新增的。此類提供一個與 StringBuffer 兼容的 API(API(Application Programming Interface,應(yīng)用程序編程接口)是一些預(yù)先定義的函數(shù),目的是提供應(yīng)用程序與開發(fā)人員基于某軟件或硬件得以訪問一組例程的能力,而又無需訪問源碼,或理解內(nèi)部工作機(jī)制的細(xì)節(jié))但不保證同步。該類被設(shè)計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區(qū)被單個線程使用的時候(這種情況很普遍)。如果可能,建議優(yōu)先采用該類,因?yàn)樵诖蠖鄶?shù)實(shí)現(xiàn)中,它比 StringBuffer 要快。兩者的方法基本相同。

字符串的操作

  • length()方法是針對字符串而言的,length屬性是針對數(shù)組而言的

提取字符串信息

可變字符串

  • char和String的區(qū)別
    char是字符類型,是基礎(chǔ)數(shù)據(jù)類型,長度固定,用單引號表示 如 c='謝';
    String是字符串類型,不是基礎(chǔ)數(shù)據(jù)類型,長度無法確定,用雙引號表示 str="傻啊"。
  • 關(guān)于String的創(chuàng)建方式:
    1、String str = new String("abc");
    需要注意的是:這條語句中str是放在棧中,new出來的字符串對象是放在堆上的,"hello"字面量是放在方法區(qū)的。
    2、String str = "abc";
    其實(shí)等效于:char data[] = {'a','b','c'}; String str = new String(data);
    3、String str = "a"+"bc";
    說明Java提供對字符串串聯(lián)符號"+"以及將其他對象轉(zhuǎn)換成字符串的特殊支持。
    當(dāng)使用任何方式來創(chuàng)建一個字符串對象str時,JVM運(yùn)行時會將這個str在String池中尋找是否存在內(nèi)容相同的字符串對象,如若不存在就在池中創(chuàng)建,否則不在池中添加。
    關(guān)于不可變類
    字符串是常量,它的值在創(chuàng)建之后不能改變,而String類的引用卻可以指向不同的字符串,因?yàn)镾tring對象時不可變的,但 是他們的地址可以共享。
  • String s = "abc" 是把String作為一個基本數(shù)據(jù)類型來使用的,因此s所引用的對象是屬于String緩沖池內(nèi)的。并且此時String緩沖池內(nèi)并沒有與其值相同的String對象存在,因此虛擬機(jī)會為此創(chuàng)建一個新的String對象,即new String("abc");
    
    String str = new String("abc"); 是把String作為一個對象來使用的,因此str所引用的對象不屬于String緩沖池內(nèi)的,即它是獨(dú)立的。通過new關(guān)鍵字,虛擬機(jī)會為此創(chuàng)建一個 新的String對象,即為它分配了一塊新的內(nèi)存堆。
    所以"=="比較后的結(jié)果是false,因?yàn)閟和str所引用的并不是同一個對象,它們是獨(dú)立存在的。而equals()方法所返回的是true,因?yàn)檫@兩個對象所封裝的字符串內(nèi)容是完全相同的。
    兩個String類型的變量str和str1都通過new關(guān)鍵字分別創(chuàng)建了一個新的String對象,這個new關(guān)鍵字為創(chuàng)建的每個對象分配一塊新的、獨(dú)立的內(nèi)存堆。
    所以通過 ==比較的是他們所引用的是否同一對象,equals比較的是兩個對象多封裝的字符串內(nèi)容。

在Object類的equals方法的本質(zhì)其實(shí)是和“==”一樣的,都是比較兩個對象引用是否指向同一個對象(即兩個對象是否為同一對象),而String類中對equals進(jìn)行了重寫才會不同。

  • Java中String是一個特殊的包裝類數(shù)據(jù)有兩種創(chuàng)建形式:
    String s = "abc";
    String s = new String("abc");
    第一種先在棧中創(chuàng)建一個對String類的對象引用變量s,然后去查找"abc"是否被保存在字符串常量池中,如果沒有則在棧中創(chuàng)建三個char型的值'a'、'b'、'c',然后在堆中創(chuàng)建一個String對象object,它的值是剛才在棧中創(chuàng)建的三個char型值組成的數(shù)組{'a'、'b'、'c'},接著這個String對象object被存放進(jìn)字符串常量池,最后將s指向這個對象的地址,如果"abc"已經(jīng)被保存在字符串常量池中,則在字符串常量池中找到值為"abc"的對象object,然后將s指向這個對象的地址。
    第一種特點(diǎn):JVM會自動根據(jù)棧中數(shù)據(jù)的實(shí)際情況來決定是否有必要創(chuàng)建新對象。
    第二種可以分解成兩步1、String object = "abc"; 2、String s = new String(object); 第一步參考第一種創(chuàng)建方式,而第二步由于"abc"已經(jīng)被創(chuàng)建并保存到字符串常量池中,因此jvm只會在堆中新創(chuàng)建一個String對象,它的值共享?xiàng)V幸延械娜齻€char型值。
    第二種特點(diǎn):一概在堆中創(chuàng)建新對象,而不管其字符串值是否相等,是否有必要創(chuàng)建新對象。
    在講字符串比較前,必須要了解==和equals的區(qū)別:
    因?yàn)閖ava所有類都繼承于Object基類,而Object中equals用==來實(shí)現(xiàn),所以equals和==是一樣的,都是比較對象地址,java api里的類大部分都重寫了equals方法,包括基本數(shù)據(jù)類型的封裝類、String類等。對于String類==用于比較兩個String對象的地址,equals則用于比較兩個String對象的內(nèi)容(值)。
    一、不變模式:

一個字符串對象創(chuàng)建后它的值不能改變。
String str1="hello";//創(chuàng)建一個對象hello,不會變;
System.out.println(str1);
str1+=" world!";//兩個字符串對象粘粘,系統(tǒng)其實(shí)創(chuàng)建了一個新的對象,把Str1的指向改了,指向新的對象;hello就 //變成了垃圾;
System.out.println(str1);
//如果一直這樣創(chuàng)建會影響系統(tǒng)的效率;要頻繁的改變字符串對象的值就用StringBuffer來描述;
StringBuffer sb=new StringBuffer("[");
sb.append("hehe");

sb.append("]");//append();不會制造垃圾,真正在改sb的值;
System.out.println(sb);

二、對象池

首先要明白,Object obj = new Object();

obj是對象的引用,它位于棧中, new Object() 才是對象,它位于堆中。

可以這樣理解obj是拴在氫氣球上的繩子,new Object() 是氫氣球,我們通過對象的引用訪問對象,就像我們那著繩子氫氣球才不會跑掉。

創(chuàng)建一個Stirng對象,主要就有以下兩種方式:

java 代碼
String str1 = new String("abc");
Stirng str2 = "abc";
雖然兩個語句都是返回一個String對象的引用,但是jvm對兩者的處理方式是不一樣的。對于第一種,jvm會馬上在heap中創(chuàng)建一個String對象,然后將該對象的引用返回。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 最先接觸編程的知識是在大學(xué)里面,大學(xué)里面學(xué)了一些基礎(chǔ)的知識,c語言,java語言,單片機(jī)的匯編語言等;大學(xué)畢...
    oceanfive閱讀 3,377評論 0 7
  • 《Java從小白到大?!芳堎|(zhì)版已經(jīng)上架了?。?! 由字符組成的一串字符序列,稱為“字符串”,在前面的章節(jié)中也多次用到...
    tony關(guān)東升閱讀 1,272評論 0 2
  • 一、字符串在C#中,字符串是一系列不可修改的Unicode字符,創(chuàng)建字符串后,就不能修改它。要創(chuàng)建字符串,最常用的...
    CarlDonitz閱讀 1,384評論 0 2
  • 字符串和字符 甲串是一系列字符,如的"hello, world"或"albatross"。Swift字符串由Str...
    Fuuqiu閱讀 1,087評論 0 0
  • 真正的朋友,不在乎數(shù)量,只在乎質(zhì)量,平時吃吃喝喝一大群,遇到困難的時候一個個逃離,你認(rèn)識的人再多,關(guān)鍵時刻沒有人幫...
    小羅簡書閱讀 192評論 0 0