JAVA-String詳解

一刑桑、面試經(jīng)常會(huì)碰到一個(gè)問(wèn)題措译,就是String不可變

大部分答的時(shí)候會(huì)講因?yàn)镾tring的源碼里面尸昧,它是這樣的

/** The value is used for character storage. */
    private final char value[];

它是被final修飾的,被final修飾的真正含義是什么呢来累?一定能講出是不可變砚作,那么到底是什么不可變啊嘹锁?我們可以來(lái)試一試

 final int[] value = new int[]{1,2,3};
 value = new int[]{1,2,4};

會(huì)報(bào)錯(cuò)

Error:(33, 9) java: 無(wú)法為最終變量value分配值

這說(shuō)明引用不可變偎巢,value不能再指向另一個(gè)變量,但是這能說(shuō)明value的值不可變嗎兼耀?我們?cè)賮?lái)試試看

final int[] value = new int[]{1,2,3};
value[1]=4;
System.out.println(value[0]+" "+value[1]+" "+value[2]);

輸出就是

1 4 3

因此压昼,final不可變指的是引用對(duì)象不可變,而不是對(duì)象的值不可變瘤运,那么到底是什么讓String對(duì)象不可變呢窍霞?再去源碼看看,是不是還有個(gè)private拯坟,這個(gè)讓value的值在外部是不可變的但金。再來(lái)看一個(gè)是如何表現(xiàn)線程安全的不可變的呢:

//現(xiàn)有一個(gè)get方法,在方法內(nèi)改變string
public static String get(String str){
        str += "aaa";
        System.out.println("get方法中str的hashcode"+str.hashCode());
        return str;
    }
//測(cè)試
String str = "123";
System.out.println("str的hashcode"+str.hashCode());
System.out.println(get(str));
System.out.println(str);
System.out.println("最后的str的hashcode"+str.hashCode());

//輸出的結(jié)果
str的hashcode48690
get方法中str的hashcode1450620111
123aaa
123
最后的str的hashcode48690

可以發(fā)現(xiàn)get方法其實(shí)形成了一個(gè)新的str郁季,而真正的str并沒有被改變
*這里有個(gè)小tip:String只能通過(guò)hashcode的方式獲得相對(duì)的jvm中的地址冷溃,但并不是真實(shí)的地址。

二梦裂、java中還有個(gè)字符串常量值的概念

先來(lái)看看神奇的地方:

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
String s4 = s3.intern();
System.out.println(s1==s2);
System.out.println( s2==s3);
System.out.println(s3==s4);
System.out.println(s4==s2);

//輸出
true
false
false
true

s1和s2竟然是一樣的似枕,這就是常量池的作用,你創(chuàng)建一個(gè)常量年柠,它會(huì)先去常量池中尋找是否已經(jīng)存在凿歼,如果存在那就引用同一個(gè),如果不存在那就放進(jìn)去冗恨,通過(guò)new操作符創(chuàng)建的字符串對(duì)象不指向字符串池中的任何對(duì)象答憔,但是可以通過(guò)使用字符串的intern()方法來(lái)指向其中的某一個(gè)。java.lang.String.intern()返回一個(gè)保留池字符串掀抹,就是一個(gè)在全局字符串池中有了一個(gè)入口虐拓。如果以前沒有在全局字符串池中,那么它就會(huì)被添加到里面傲武。
因此蓉驹,使用new創(chuàng)建對(duì)象的時(shí)候是會(huì)創(chuàng)建兩個(gè)對(duì)象或者一個(gè)對(duì)象,它的過(guò)程是先去常量池中尋找是否有谱轨,如果有戒幔,則再堆中(常量池在方法區(qū)中)創(chuàng)建一個(gè)新的對(duì)象并指向它,如果沒有土童,則在常量池中先創(chuàng)建一個(gè)诗茎,再在堆中創(chuàng)建一個(gè),還是指向堆中的,不信咱們來(lái)看看

String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1==s2);

輸出是false敢订,因此使用new創(chuàng)建出來(lái)的必定是指向堆里面的王污。

三、字符串拼接

最經(jīng)典就是+號(hào)問(wèn)題了楚午,那么String s = s1 + s2到底是個(gè)啥昭齐,和String s = "hello"+"world"有啥區(qū)別嗎?其實(shí)他們打印輸出的結(jié)果是一樣的矾柜,只不過(guò)底層的方式是不一樣的

String s = s1 + s2;

這種方式阱驾,是在底層先創(chuàng)建一個(gè)StringBuilder對(duì)象,然后進(jìn)行兩次append操作怪蔑,最后再toString一下輸出里覆,而new一個(gè)StringBuilder對(duì)象是在堆中,所以操作都是在堆中完成的

String s = "hello" + "world";

這種方式缆瓣,編譯的時(shí)候會(huì)認(rèn)為+號(hào)是沒用的喧枷,所以實(shí)際上等同于

String s ="helloworld";

因此當(dāng)問(wèn)到String,StringBuilder弓坞,StringBuffer的問(wèn)題時(shí)隧甚,為啥String做字符串拼接的效率是最低的就有答案了,它會(huì)創(chuàng)建新的對(duì)象放在堆里面渡冻,如果循環(huán)太多而gc來(lái)不及收回戚扳,那么堆中會(huì)被占用大量的空間。

想起來(lái)還有String的內(nèi)容再接著補(bǔ)充吧

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末菩帝,一起剝皮案震驚了整個(gè)濱河市咖城,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌呼奢,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件切平,死亡現(xiàn)場(chǎng)離奇詭異握础,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)悴品,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門禀综,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人苔严,你說(shuō)我怎么就攤上這事定枷。” “怎么了届氢?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵欠窒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我退子,道長(zhǎng)岖妄,這世上最難降的妖魔是什么型将? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮荐虐,結(jié)果婚禮上七兜,老公的妹妹穿的比我還像新娘。我一直安慰自己福扬,他們只是感情好腕铸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铛碑,像睡著了一般恬惯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亚茬,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天酪耳,我揣著相機(jī)與錄音,去河邊找鬼刹缝。 笑死碗暗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梢夯。 我是一名探鬼主播言疗,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼颂砸!你這毒婦竟也來(lái)了噪奄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤人乓,失蹤者是張志新(化名)和其女友劉穎勤篮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體色罚,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碰缔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戳护。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片金抡。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腌且,靈堂內(nèi)的尸體忽然破棺而出梗肝,到底是詐尸還是另有隱情,我是刑警寧澤铺董,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布巫击,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喘鸟。R本人自食惡果不足惜匆绣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望什黑。 院中可真熱鬧崎淳,春花似錦、人聲如沸愕把。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)恨豁。三九已至嚣镜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橘蜜,已是汗流浹背菊匿。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留计福,地道東北人跌捆。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像象颖,于是被迫代替她去往敵國(guó)和親佩厚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 從網(wǎng)上復(fù)制的说订,看別人的比較全面抄瓦,自己搬過(guò)來(lái),方便以后查找陶冷。原鏈接:https://www.cnblogs.com/...
    lxtyp閱讀 1,345評(píng)論 0 9
  • String是最常使用的Java類之一钙姊,整理的了一些重要的String知識(shí)分享給大家。 作為一個(gè)Java新手程序員...
    __元昊__閱讀 924評(píng)論 0 4
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的埃叭。我們天天就是要...
    二毛_coder閱讀 455評(píng)論 1 1
  • 使用Java語(yǔ)言進(jìn)行編程摸恍,我們每天都要用到String類,但是以前只是拿來(lái)就用赤屋,并不知道String類的實(shí)現(xiàn)原理和...
    lunabird閱讀 433評(píng)論 0 1
  • String類 先看一下源碼(jdk1.8.0_144)中的對(duì)于類的定義 首先可以看到String類是被final...
    efan閱讀 593評(píng)論 1 1