27

是什麼這2碼之間的差:爪哇通過引用傳遞

代碼A:

Foo myFoo; 
myFoo = createfoo(); 

其中

public Foo createFoo() 
{ 
    Foo foo = new Foo(); 
    return foo; 
} 

比。代碼B:

Foo myFoo; 
createFoo(myFoo); 

public void createFoo(Foo foo) 
{ 
    Foo f = new Foo(); 
    foo = f; 
} 

這兩段代碼有什麼不同嗎?

+7

那裏沒有「通過引用」。它通過價值傳遞,價值是一個參考。代碼B不編譯,如果它不會改變myFoo。 – harold 2012-02-22 23:05:36

回答

165

Java總是通過值傳遞參數而不是通過引用。


讓我通過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"); 
    } 
} 

我將在步驟解釋:

  1. 聲明名爲Foof參考並將其分配給新對象Foo,屬性"f"

    Foo f = new Foo("f"); 
    

    enter image description here

  2. 從方法方面,Foo類型的具有名稱a參考被聲明和它的最初分配給null

    public static void changeReference(Foo a) 
    

    enter image description here

  3. 作爲調用方法changeReference,參考a將被分配給其被作爲參數傳遞的對象。

    changeReference(f); 
    

    enter image description here

  4. 聲明名爲Foo類型的b,並將其與一個屬性"b"分配給Foo類型的新對象引用。

    Foo b = new Foo("b"); 
    

    enter image description here

  5. a = b重新分配所述參考a NOT f到其它的屬性是"b"的對象。

    enter image description here


  6. 作爲調用modifyReference(Foo c)方法,創建了一個參考c和分配給該對象與屬性"f"

    enter image description here

  7. c.setAttribute("c");會改變引用c指向它的對象的屬性,它的引用f指向它同一個對象。

    enter image description here

我希望你現在知道如何傳遞對象作爲參數在工作方法參數作爲自己的變量聲明的Java :)

+15

真棒解釋!我覺得開悟了! – delita 2012-02-22 23:48:53

+10

聖牛。這已被多次提出並回答,但這是我見過的最精巧和最具藝術性的解決方案。好樣的! – duffymo 2012-02-23 01:13:39

+0

你能比較一下「通過參考」的樣子嗎?對我來說有意義的是「傳遞值」,它傳遞f所引用的對象的內存地址。在** changeReference **中,** a **是一個新的變量,指向相同的內存地址,改變** **的值(或稱爲內存地址)只會改變** a **指向的內容而不是** f **。如果它是「通過引用傳遞」** f **將被傳入,所以** a = f **,更改** a **的值(或引用的內存地址)會改變** f ** – 2013-10-09 16:59:13

8

由於Java嚴格按照值傳遞,即使對象的引用是按值傳遞的,第二個代碼也不會按預期工作。關於此,請參閱衆多討論的「相關」部分。

2

思考。如果你是用一個單一的代碼塊替換方法調用,它看起來像這樣:

Foo myFoo; 
{      //Method call starts here 
    Foo foo; 
    foo = myFoo; 
    Foo f = new Foo(); 
    foo = f; 
}      //Method call ends here 

即使方法參數具有相同的名稱作爲另一個變量,方法參數仍然是它自己的,獨一無二的參考只有方法知道。這與Eng.Fouad上面所說的一樣。

1

您應該知道的另一個重點是您傳入該方法的對象類型。無論它是可變對象還是不可變對象。如果你傳遞一個不可變的對象,例如String,它將創建另一個副本並進行修改。更改不會反映到您的原始副本。

+0

不,在語言中沒有「可變」或「不可變」的概念。因此,他們如何通過沒有區別。 「更改不會反映到您的原始副本。」根據定義,一個不可改變的對象是沒有辦法「改變」的,因此這個陳述沒有意義。 – newacct 2013-01-16 19:18:05