call by value or reference ?

Java中參數(shù)傳遞是傳值還是傳引用呢滑沧?很多人遇到這個(gè)問題都會(huì)馬上給你拋出這個(gè)例子:


對(duì)方不想和你說話并向你拋了一段代碼
class Entry{
    Integer value;
    public Entry(Integer v){
        this.value = v;
    }
   @Override
    public String toString() {
        return "Entry[value=" + value + "]";
    }
}
public class CallByDemo{
    public static void swap(int a,int b){
        int temp = a;
        a = b;
        b = a;
    }
    public static void swap(Entry e1,Entry e2){
        Integer temp = e1.value;
        e1.value = e2.value;
        e2.value = temp;
    }
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        System.out.println("before:a="+a+",b="+b);
        swap(a,b);
        System.out.println("after :a="+a+",b="+b);
        Entry e1 = new Entry(new Integer(1000));
        Entry e2 = new Entry(new Integer(2000));   
        System.out.println("before:e1="+e1+"e2="+e2);
        swap(e1,e2);
        System.out.println("after :e1="+e1+"e2="+e2);
    }
}

運(yùn)行結(jié)果:

before:a=1,b=2
after :a=1,b=2
before:e1=Entry[value=1000]e2=Entry[value=2000]
after : e1=Entry [value=2000 ]e2=Entry[value=1000]

然后言之鑿鑿地拋出這個(gè)結(jié)論:

  1. 當(dāng)參數(shù)為基本類型時(shí)為傳值
  2. 當(dāng)參數(shù)為對(duì)象引用類型為傳引用

好像沒有毛病啊,但是如果我把swap(Entry e1,Entry e2)改成這樣呢膝昆?

public static void swap(Entry e1,Entry e2){
    Entry temp = e1;//Integer temp = e1.value;
    e1 = e2;   //e1.value = e2.value;
    e2 = temp;//e2.value = temp;
}

再次運(yùn)行發(fā)現(xiàn)結(jié)果變成了這樣:

before:a=1,b=2
after :a=1,b=2
before:e1=Entry[value=1000]e2=Entry[value=2000]
after : e1=Entry [value=1000 ]e2=Entry[value=2000]

什么叠必?怎么會(huì)這樣纬朝?

為了解釋這個(gè)問題收叶,我們不妨看一下Java運(yùn)行時(shí)內(nèi)存結(jié)構(gòu):


Java Run-Time Data Areas

Java堆 (Java Heap)

  1. 作用:存放幾乎所有的對(duì)象實(shí)例和數(shù)組
  2. 組成
    • 新生代(Young Generation)
      • Eden區(qū):存放新創(chuàng)建的對(duì)象或短期的對(duì)象
      • Survivor區(qū):存放GC后的幸存的或中期的對(duì)象
    • 老年代(Old Generation):存放GC多次后始終存在或者長(zhǎng)期的對(duì)象及Survivor區(qū)放不下的大對(duì)象
    • 永久代(Permanent Generation):永久代在JDK8中被完全地移除
  3. 是否線程共享:是

Java虛擬機(jī)棧(JVM Stacks)

  1. 作用:存放棧幀
  2. 組成:棧幀
  3. 是否線程共享:線程私有的,生命周期和線程的相同

棧幀(Stack Frame)
- 作用:方法在執(zhí)行的時(shí)候澄峰,都會(huì)有一個(gè)棧幀創(chuàng)建出來俏竞,用于存儲(chǔ)局部變量表、操作數(shù)棧堂竟、動(dòng)態(tài)鏈接、方法出口等信息
- 組成:
- 局部變量表(Local Variables):存放編譯時(shí)可知的各種基本數(shù)據(jù)類型跃捣、對(duì)象引用
- 操作數(shù)棧(Operand Stacks):供方法調(diào)用時(shí)進(jìn)行各種運(yùn)算
- 動(dòng)態(tài)鏈(Dynamic Linking):
- 方法出口

方法區(qū)(Method Area)

  1. 作用:存放被虛擬機(jī)加載的類的結(jié)構(gòu)信息(如:字段和方法數(shù)據(jù)、方法的字節(jié)碼疚漆、運(yùn)行時(shí)常量池等)、常量刁赦,靜態(tài)變量及類、實(shí)例甚脉、接口初始化時(shí)用到的特殊方法丸升。
  2. 組成:方法區(qū)是堆的邏輯組成部分(有人稱之為永久代 Permanent Generation)
  3. 是否線程共享:是

本地方法棧(Native Method Stacks)

  1. 作用:存放本地方法調(diào)用時(shí)的棧幀
  2. 組成:棧幀
  3. 是否線程共享:線程私有的,生命周期和線程的相同
  4. 虛擬機(jī)執(zhí)行Native方法時(shí)使用牺氨,不同的虛擬機(jī)有不同的實(shí)現(xiàn)方法墩剖,HotSpot虛擬機(jī)的本地方法棧和虛擬機(jī)棧合二為一。

PC寄存器/程序計(jì)數(shù)器(pc Register)

  1. 作用:保存JVM正在執(zhí)行方法的字節(jié)碼指令的地址,如果該方法為native本地方法則為undefined
  2. 組成:一塊至少能夠保存一個(gè)本地指針或者returnAddress的值的內(nèi)存空間
  3. 是否線程共享:每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,各個(gè)線程之間計(jì)數(shù)器互不影響沼头,獨(dú)立存儲(chǔ)

OK进倍,我們?cè)賮矸治鲆幌律厦娴膯栴}:

內(nèi)存結(jié)果分析

其實(shí)呢,Java采用的是傳值(call by value)猾昆,形參只是實(shí)際參數(shù)的一個(gè)拷貝毡庆,形參不能修改實(shí)參的內(nèi)容。

  1. 當(dāng)值為基本數(shù)據(jù)類型時(shí)么抗,swap(int,int)方法中的局部變量a,b接收傳入的值并保存在與該方法對(duì)應(yīng)的棧幀的局部變量表中毅否。而main方法中的a,b保存在main方法對(duì)應(yīng)的棧幀的局部變量表中,修改swap方法中的a,b對(duì)main方法中的a,b沒有任何影響蝇刀,所以交換失敗螟加。

  2. 當(dāng)值為引用類型時(shí),傳入方法的也是它的一個(gè)拷貝吞琐,當(dāng)然這個(gè)拷貝有點(diǎn)特殊捆探,它是Java Heap中的對(duì)象(Entry_e1、Entry_e2)的一個(gè)引用站粟。該引用也保存在對(duì)應(yīng)的棧幀的局部變量表中黍图,修改swap方法中的e1,e2的引用指向?qū)ain方法中的e1,e2沒有任何影響,所以交換失敗奴烙。但局部變量e1,e2可以通過引用改變Heap中的對(duì)象的狀態(tài)助被,如第一段代碼中在swap中的局部變量可以通過引用來修改Heap中的對(duì)象的value屬性,從而達(dá)到交換屬性中的目的切诀。
    此外揩环,需要注意的是Java中的某些類如:String、基本類型的包裝類幅虑、BigInteger丰滑、BigDecimal是不可變的,即無法修改其內(nèi)容倒庵。

最后總結(jié)一句:Java是方法調(diào)用是值傳遞褒墨!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炫刷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子貌亭,更是在濱河造成了極大的恐慌柬唯,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圃庭,死亡現(xiàn)場(chǎng)離奇詭異锄奢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剧腻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門拘央,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人书在,你說我怎么就攤上這事灰伟。” “怎么了儒旬?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵栏账,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我栈源,道長(zhǎng)挡爵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任甚垦,我火速辦了婚禮茶鹃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘艰亮。我一直安慰自己闭翩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布迄埃。 她就那樣靜靜地躺著疗韵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侄非。 梳的紋絲不亂的頭發(fā)上蕉汪,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音彩库,去河邊找鬼。 笑死先蒋,一個(gè)胖子當(dāng)著我的面吹牛骇钦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播溢豆,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼娄蔼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了项贺?” 一聲冷哼從身側(cè)響起鳞仙,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寇蚊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棍好,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗岸,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年借笙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扒怖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡业稼,死狀恐怖盗痒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情低散,我是刑警寧澤俯邓,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站熔号,受9級(jí)特大地震影響稽鞭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜跨嘉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一川慌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祠乃,春花似錦梦重、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嘱支,卻和暖如春蚓胸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背除师。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工沛膳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人汛聚。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓锹安,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叹哭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

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

  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分忍宋,分別是: ...
    光劍書架上的書閱讀 2,504評(píng)論 2 26
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司风罩,掛了不少糠排,但最終還是拿到小米、百度超升、阿里入宦、京東、新浪廓俭、CVTE云石、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,243評(píng)論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法研乒,內(nèi)部類的語(yǔ)法汹忠,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法雹熬,線程的語(yǔ)...
    子非魚_t_閱讀 31,625評(píng)論 18 399
  • 層次高的人竿报,他們更懂得“感同身受”和換位思考铅乡,知道每個(gè)人都不容易,懂得尊重別人烈菌。 01 意大利插畫家Marco M...
    寧叔閱讀 169評(píng)論 0 0