這篇文章給大家介紹Java方法傳參時(shí)采用哪種傳遞,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
創(chuàng)新新互聯(lián),憑借十載的網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)經(jīng)驗(yàn),本著真心·誠心服務(wù)的企業(yè)理念服務(wù)于成都中小企業(yè)設(shè)計(jì)網(wǎng)站有上千多家案例。做網(wǎng)站建設(shè),選創(chuàng)新互聯(lián)公司。
我們來看一個(gè)新手甚至寫了多年Java的朋友都可能不是十分確定的問題:
在Java方法傳參時(shí),究竟是引用傳遞還是值傳遞?
為了說明問題, 我給出一個(gè)非常簡單的class定義:
public class Foo { String attribute; Foo(String s) { this.attribute = s; } void setAttribute(String s) { this.attribute = s; } String getAttribute() { return this.attribute; } }
下面在闡明觀點(diǎn)時(shí),可能會(huì)多次用到該類。
關(guān)于Java里值傳遞還是引用傳遞,至少從表現(xiàn)形式上來看,兩種觀點(diǎn)都有支撐的論據(jù)。下面我來一一分析:
觀點(diǎn)1:引用傳遞
理由如下:先看一段代碼
public class Main { public static void modifyReference(Foo c){ c.setAttribute("c"); // line DDD } public static void main(String[] args) { Foo fooRef = new Foo("a"); // line AAA modifyReference(fooRef); // line BBB System.out.println(fooRef.getAttribute()); // 輸出 c } }
上述示例,輸出結(jié)果為"c",而不是"c"。
我們?cè)趌ine AAA處新創(chuàng)建了一個(gè)Object Foo并將其引用fooRef在line BBB處傳給了方法modifyReference()的參數(shù)cRef, 該方法內(nèi)部處理后,fooRef指向的Object中的值從"a"變成了"c", 而引用fooRef還是那個(gè)引用, 因此,我們是否可以認(rèn)為,在line BBB處發(fā)生了引用傳遞?
先留著疑問,我們繼續(xù)往下看。
觀點(diǎn)2:值傳遞
繼續(xù)看一段代碼
public class Main { public static void changeReference(Foo aRef){ Foo bRef = new Foo("b"); aRef = bRef; // line EEE } public static void main(String[] args) { Foo fooRef = new Foo("a"); // line AAA changeReference(fooRef); // line BBB System.out.println(fooRef.getAttribute()); // 輸出 a } }
上述示例,輸出結(jié)果為"a", 而不是"b"。
我們?cè)趌ine AAA處新創(chuàng)建了一個(gè)Object Foo并將其引用fooRef在line EEE處傳給了方法changeReference()的參數(shù)aRef, 該方法內(nèi)部引用aRef在line DDD處被重新賦值。如果是引用傳遞,那么引用aRef在line EEE處已經(jīng)被指向了新的Object, 輸出應(yīng)該為"b"才對(duì),事實(shí)上是怎樣的呢?事實(shí)上輸出了"b",也就是說changeReference()方法改變了傳入引用所指對(duì)象的值。
觀點(diǎn)1和觀點(diǎn)2的輸出結(jié)果多少會(huì)讓人有些困惑,別急,我們繼續(xù)往下看。
深入分析
為了詳細(xì)分析這個(gè)問題,把上述兩段代碼合起來:
public class Main { public static void modifyReference(Foo cRef){ cRef.setAttribute("c"); // line DDD } public static void changeReference(Foo aRef){ Foo bRef = new Foo("b"); // line FFF aRef = bRef; // line EEE } public static void main(String[] args) { Foo fooRef = new Foo("a"); // line AAA changeReference(fooRef); // line BBB System.out.println(fooRef.getAttribute()); // 輸出 a modifyReference(fooRef); // line CCC System.out.println(fooRef.getAttribute()); // 輸出 c } }
下面來深入內(nèi)部來詳細(xì)分析一下引用和Object內(nèi)部的變化。來看下面圖示:
① Line AAA, 申明一個(gè)名叫fooRef,類型為Foo的引用,并見其分配給一個(gè)新的包含屬性值為"f"的對(duì)象,該對(duì)象類型為Foo。
Foo fooRef = new Foo("a"); // line AAA
② Line DDD, 方法內(nèi)部,申明了一個(gè)Foo類型的名為aRef的引用,且aRef被初始化為null。
void changeReference(Foo a);
③ Line CCC, changeReference()方法被調(diào)用后,引用aRef被分配給fooRef指向的對(duì)象。
changeReference(fooRef);
④ Line FFF, 申明一個(gè)名叫bRef,類型為Foo的引用,并見其分配給一個(gè)新的包含屬性值為"b"的對(duì)象,該對(duì)象類型為Foo。
Foo bRef = new Foo("b");
⑤ Line EEE, 將引用aRef重新分配給了包含屬性"b"的對(duì)象。此處注意,并非將fooRef重新分配,而是aRef。
aRef = bRef;
⑥ Line CCC, 調(diào)用方法modifyReference(Foo cRef)后,新建了一個(gè)引用cRef并將之分配到包含該屬性"f"的對(duì)象上,該對(duì)象同時(shí)被兩個(gè)引用fooRef和cRef指向著。
modifyReference(fooRef);
⑦ Line DDD, cRef.setAttribute("c");將會(huì)改變cRef引用指向的包含屬性"f"的對(duì)象,而該對(duì)象同時(shí)被引用fooRef指向著。
cRef.setAttribute("c");
此時(shí)引用fooRef指向的對(duì)象內(nèi)部屬性值"f"也被重新設(shè)置為"c"。
Java內(nèi)部方法傳參不是引用傳遞,而是引用本身的"值"的傳遞,歸根結(jié)底還是值傳遞。將一個(gè)對(duì)象的引用fooRef傳給方法的形參newRef,將給該對(duì)象新增了一個(gè)引用,相當(dāng)于多了一個(gè)alias。我們可以通過這個(gè)原引用fooRef,或這是方法參數(shù)里的新引用newRef去訪問、操作原對(duì)象,也可以改變參數(shù)里的引用newRef本身的值,卻無法改變?cè)胒ooRef的值。
關(guān)于Java方法傳參時(shí)采用哪種傳遞就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。