Java字符串可以引用傳遞嗎早敬?

對(duì)于絕大多數(shù)的初級(jí)程序員或者說(shuō)不重視“內(nèi)功”的老鳥(niǎo)來(lái)說(shuō)趁耗,往往停留在“知其然不知其所以然”的層面上——會(huì)用沉唠,略知一二,但要求他把問(wèn)題說(shuō)清楚的時(shí)候苛败,就只能撓撓頭雙手一攤一張問(wèn)號(hào)臉了满葛。

好了,讓我們來(lái)步入正題罢屈。先來(lái)看一段有趣但令人困惑的代碼片段吧嘀韧。

public static void main(String[] args) {  
  String x = new String("沉默王二");  
  change(x);   
  System.out.println(x);
}
public static void change(String x) {   
   x = "沉默王三";
}

從代碼的字面邏輯來(lái)看,程序應(yīng)該輸出“沉默王三”缠捌,但事與愿違锄贷,程序輸出的結(jié)果卻是“沉默王二”。change() 方法做的是無(wú)用功,因?yàn)?String 是值傳遞而不是引用傳遞谊却。引用傳遞可以在被調(diào)用的方法中對(duì)實(shí)參進(jìn)行修改柔昼,但值傳遞卻不可以。為什么呢炎辨?

x 存儲(chǔ)的是一個(gè)引用捕透,該引用指向內(nèi)存中的“沉默王二”字符串對(duì)象。當(dāng)我們把 x 作為參數(shù)傳遞給 change() 方法時(shí)蹦魔,x 仍然指向的是內(nèi)存中“沉默王二”字符串激率,就像下面這幅圖表達(dá)的意思一樣。

image.png

那么問(wèn)題來(lái)了勿决。正因?yàn)?Java 是值傳遞乒躺,x 的值是“沉默王二”的引用。那么當(dāng) change() 方法被調(diào)用的時(shí)候低缩,x 不是剛好指向了內(nèi)存中新創(chuàng)建的字符串對(duì)象“沉默王三”了嗎嘉冒?就像下面這幅圖表達(dá)的意思那樣。

image.png

哦咆繁,看起來(lái)是一個(gè)很完美的解釋?zhuān)瑢?duì)吧讳推?但這樣的解釋存在一些問(wèn)題。

當(dāng)字符串“沉默王二”被創(chuàng)建的時(shí)候玩般,Java 會(huì)在內(nèi)存中申請(qǐng)一小段空間银觅,用來(lái)存儲(chǔ)這個(gè)字符串對(duì)象。然后呢坏为,把對(duì)象的引用指向了變量 x究驴,也就是說(shuō),變量 x 實(shí)際上存儲(chǔ)的是對(duì)象的引用(對(duì)象在內(nèi)存中存儲(chǔ)的地址)匀伏。

我相信大家對(duì)上面這一點(diǎn)(對(duì)象和對(duì)象引用)已經(jīng)完全理解了洒忧。

關(guān)鍵的點(diǎn)來(lái)了。當(dāng)變量 x 作為參數(shù)(實(shí)參)傳遞給 change() 方法時(shí)够颠,實(shí)際上傳遞的是 x 的一個(gè)拷貝(形參)熙侍。在 change() 方法中,形參 x 起先引用的也是“沉默王二”這個(gè)對(duì)象履磨,當(dāng)執(zhí)行 x = "沉默王三" 的時(shí)候蛉抓,會(huì)在內(nèi)存中創(chuàng)建新的字符串“沉默王三”,然后形參 x 不再引用“沉默王二”這個(gè)對(duì)象了剃诅,改為引用“沉默王三”這個(gè)對(duì)象了巷送。但實(shí)參 x 呢?并沒(méi)有發(fā)生任何的改變综苔!就像下面這幅圖一樣惩系。

image.png

假如我們真的需要改變字符串呢?那就不能使用 String 類(lèi)了如筛,最好使用 StringBuilder堡牡,來(lái)擼一串代碼吧。

public static void main(String[] args) {
    StringBuilder x = new StringBuilder("沉默王二");   
    change(x);  
    System.out.println(x);}
public static void change(StringBuilder x) {  
    x.delete(3,4).append("三");
}

上述代碼會(huì)輸出“沉默王三”杨刨,但假如我們使用 new 關(guān)鍵字重新對(duì)形參 x 進(jìn)行賦值晤柄,就無(wú)濟(jì)于事。

public static void main(String[] args) {   
   StringBuilder x = new StringBuilder("沉默王二");   
   change(x); 
   System.out.println(x);
}
public static void change(StringBuilder x) {   
   x = new StringBuilder("沉默王三");
}

程序輸出的結(jié)果仍然是“沉默王二”妖胀,原因其實(shí)和 String 一樣芥颈,change() 方法在內(nèi)存中創(chuàng)建了新的字符串“沉默王三”,然后形參 x 不再引用“沉默王二”這個(gè)對(duì)象赚抡,改為引用“沉默王三”這個(gè)對(duì)象了爬坑。但實(shí)參 x 并沒(méi)有任何改變。

看到這涂臣,有些讀者可能更疑惑了盾计。x = new StringBuilder("沉默王三") 不可以改變實(shí)參,而 x.delete(3,4).append("三") 卻可以赁遗,為什么署辉?為什么?為什么岩四?為什么呢哭尝?

不要著急,我們來(lái)分析一下 delete() 方法的源碼剖煌。

public AbstractStringBuilder delete(int start, int end) {  
  int len = end - start;  
  if (len > 0) {   
     System.arraycopy(value, start+len, value, start, count-end);  
      count -= len;  
   }   
  return this;
}

其中 value 是一個(gè)字符數(shù)組材鹦,用來(lái)存儲(chǔ)字符序列;count 用來(lái)表示字符序列中實(shí)際有效的字符數(shù)量末捣。

當(dāng) count -= len 執(zhí)行之前侠姑,value 的字符內(nèi)容為“沉默王二”,count 為 4箩做。我是怎么知道的呢莽红?通過(guò) IDEA 的 debug 視圖,截圖為證邦邦。

image.png

當(dāng) count -= len 執(zhí)行之后安吁,value 的字符內(nèi)容仍然為“沉默王二”,但 count 變成了 3燃辖。

image.png

當(dāng)鼠標(biāo)停留在 this 上時(shí)鬼店,此時(shí)的字符內(nèi)容為“沉默王”,也就意味著 x 當(dāng)前的字符內(nèi)容為“沉默王”黔龟。同樣的妇智,當(dāng)我們?cè)?append() 方法上進(jìn)行 debug 的時(shí)候滥玷,也可以觀察到字符串發(fā)生變化的細(xì)節(jié)。

image.png

當(dāng) append() 方法執(zhí)行結(jié)束后巍棱,此時(shí)形參 x 的字符內(nèi)容為“沉默王三”惑畴。

image.png

當(dāng) change() 方法執(zhí)行完后,此時(shí)實(shí)參 x 的字符內(nèi)容為“沉默王三”航徙。

image.png

通過(guò)上面的源碼分析如贷,大家應(yīng)該會(huì)發(fā)現(xiàn)另外一個(gè)事實(shí):x 對(duì)象始終是“StringBuilder@512”,這意味著什么呢到踏?一圖勝千言杠袱,畫(huà)個(gè)圖大家一看就明白了。

image.png

由于形參 x 和實(shí)參 x 引用的都是同一個(gè)對(duì)象窝稿,那么 change() 方法執(zhí)行結(jié)束后楣富,實(shí)參 x 的字符內(nèi)容自然也就發(fā)生了變化。

綜上所述:Java 字符串不是引用傳遞而是值傳遞伴榔;更進(jìn)一步的說(shuō)菩彬,Java 只有值傳遞,沒(méi)有引用傳遞潮梯。

作者:沉默王二
鏈接:https://juejin.im/post/5e0e6b84e51d4540ec4f40a9
來(lái)源:掘金
著作權(quán)歸作者所有骗灶。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處秉馏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耙旦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子萝究,更是在濱河造成了極大的恐慌免都,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帆竹,死亡現(xiàn)場(chǎng)離奇詭異绕娘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)栽连,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)险领,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人秒紧,你說(shuō)我怎么就攤上這事绢陌。” “怎么了熔恢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵脐湾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我叙淌,道長(zhǎng)秤掌,這世上最難降的妖魔是什么愁铺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮闻鉴,結(jié)果婚禮上帜讲,老公的妹妹穿的比我還像新娘。我一直安慰自己椒拗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布获黔。 她就那樣靜靜地躺著蚀苛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玷氏。 梳的紋絲不亂的頭發(fā)上堵未,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音盏触,去河邊找鬼渗蟹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赞辩,可吹牛的內(nèi)容都是我干的雌芽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼辨嗽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼世落!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起糟需,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤屉佳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后洲押,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體武花,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年杈帐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了体箕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挑童,死狀恐怖干旁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炮沐,我是刑警寧澤争群,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站大年,受9級(jí)特大地震影響换薄,放射性物質(zhì)發(fā)生泄漏玉雾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一轻要、第九天 我趴在偏房一處隱蔽的房頂上張望复旬。 院中可真熱鬧,春花似錦冲泥、人聲如沸驹碍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)志秃。三九已至,卻和暖如春嚼酝,著一層夾襖步出監(jiān)牢的瞬間浮还,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工闽巩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钧舌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓涎跨,卻偏偏與公主長(zhǎng)得像洼冻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隅很,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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