參考:http://ifeve.com/stackoverflow-reference-or-value/
http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value
在Java的規(guī)范里說明了在Java中一切參數(shù)都是按值傳遞的,根本就沒有引用傳遞這一說奏窑。
理解這個概念的關(guān)鍵是要明白:
Dog myDog;
這里聲明的并不是一個Dog對象,而是一個指向Dog對象的指針墨叛。
這是什么意思呢漠趁,就是當(dāng)你執(zhí)行:
Dog myDog = new Dog("Rover");
foo(myDog);
本質(zhì)上是你把創(chuàng)建好的Dog對象的地址傳遞給foo方法。(我說的‘本質(zhì)上’其實是因為Java中的指針并不是直接的地址丸边,不過可以簡單的理解成這樣)纬朝。
假設(shè)Dog對象在內(nèi)存中的地址是42共苛。那我們就是把42這個值傳遞給了foo方法隅茎。
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
讓我們來看看執(zhí)行的時候會發(fā)生些什么绸硕。
- someDog的值設(shè)置為42出嘹。
- 在AAA行
a.someDog指向一個內(nèi)存地址為42的Dog對象。
b.把Dog(內(nèi)存地址為42)對象的name屬性改為Max垮斯。 - 在BBB行
a.一個新的Dog對象被創(chuàng)建丸升,我們假設(shè)它的內(nèi)存地址是74。
b.把這個74的內(nèi)存地址值賦給someDog夷狰。 - 在CCC行
a.someDog指向一個內(nèi)存地址為74的Dog對象。
b.把Dog(內(nèi)存地址為74)對象的name屬性改為Rowlf土至。 - 方法執(zhí)行完畢陶因。
現(xiàn)在讓我們來想想在這個方法外面發(fā)生了什么:
myDog改變了嗎贴见?
這個問題的關(guān)鍵在于:
要明確myDog是一個指針螟加,而不是一個實際的Dog對象。所以答案是它沒有改變站粟,myDog的值還是42奴烙;它指向的還是最開始的那個Dog對象(雖然在foo方法中的AAA行把它指向?qū)ο蟮膎ame屬性改成了Max,但是它指向的還是那個最初的Dog對象)幅虑。
這驗證了改變所指對象的屬性,但沒有改變其指向。
Java的運(yùn)行機(jī)制跟C很像绍申。你可以給一個指針賦值胃碾,然后把這個指針傳遞給一個方法书在,之后在這個方法中你可以改變這個指針指向?qū)ο蟮臄?shù)據(jù),但是你不能改變這個指針的指向栈源。
在C++涣雕,Ada,Pascal以及其他支持引用傳遞的語言中你可以直接改變傳遞的參數(shù)兑障。如果Java是引用傳遞的話逞怨,那么在執(zhí)行上面定義的foo方法的BBB行的時候someDog的指向就會被改變眯搭。
Let me explain this through an example:
public class Main{
public static void main(String[] args){
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a){
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c){
c.setAttribute("c");
}
}
I will explain this in steps:
1.Declaring a reference named f of type Foo and assign it to a new object of type Foo with an attribute "f".
Foo f = new Foo("f");

2.From the method side, a reference of type Foo with a name a is declared and it's initially assigned to null.
public static void changeReference(Foo a)

3.As you call the method changeReference, the reference a will be assigned to the object which is passed as an argument.
changeReference(f);

4.Declaring a reference named b of type Foo and assign it to a new object of type Foo with an attribute "b".
Foo b = new Foo("b");

5.a = b is re-assigning the reference a NOT f to the object whose its attribute is "b".

6.As you call modifyReference(Foo c) method, a reference c is created and assigned to the object with attribute "f".

7.c.setAttribute("c"); will change the attribute of the object that reference c points to it, and it's same object that reference f points to it.
