2014-03-05 69 views
1

我熟悉的Java中的參考概念呼叫,但看到這個代碼後,我很困惑java編寫參考歧義

public class App 
{ 
    public static void main(String[] args) 
    { 
     Test t1 = new Test(1); 
     Test t2 = new Test(8); 
     App.doSomething(t1, t2); 
     System.out.print(t1.a); 
     System.out.print(t2.a); 
    } 
    public static void doSomething(Test t1, Test t2){ 
     System.out.print(t1.a++); 
     System.out.print(t2.a++); 
     t1 = new Test(999); 
     t2 = new Test(888); 
    } 
} 

打印來電主函數中的「t1.a」和「t1.b」變爲888和999?

+3

這是幾乎在[是Java「傳遞引用」?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference)中涵蓋的確切場景'+ +'突變對象的內部狀態,'='在本地重新分配引用。 – Radiodef

回答

5

Java沒有通過引用調用。所有參數都按值傳遞 - 但在參數是對象的情況下,傳遞的「值」是對該對象的引用。因此,如果您在該方法內使用本地對該對象的引用來修改該對象,它將修改相同的對象。但是,如果將某些內容分配給該局部變量,則不再具有對原始對象的引用,並且後續更改不會影響原始對象。

0

這就是爲什麼你通常設置你的方法參數最終 - 避免這種混亂的:)的FindBugs實際上會產生這個效果

0

這是因爲在Java參數總是pass-by-value風格警告。

在你的例子中,你傳遞一個對象的引用,但是這個引用是通過值傳遞的。換句話說,創建新的局部變量t1,並使用對參數中傳遞的對象的引用進行初始化。因此,當您將new Test()分配給它時,只有局部變量引用新對象。

0

在Java中,一切都是按價值傳遞的。 2 t1和t2的範圍是不同的。一個在main()的範圍內,另一個在doSomething()的範圍內。所以它不會變成888或999的原因是因爲離開doSomething()後這些值不存在。

0

新手也很難用這個,我會嘗試以故事的形式來解釋:

如果我借給你我的便條(我在上面的名字)與指向箭頭紅色的沙發,你拿我的粘滯便箋和抹去我的箭頭,並穿上綠色沙發上的新箭頭。當你完成你的惡作劇時,我會在上面粘上一張便籤,上面寫着綠色的沙發。我的stickynote被改變了。

但是,如果我讓你借我的名字粘上我的名字,它有一個指向紅色沙發的箭頭,你把我的粘滯便箋放在一邊,然後你做一個新的粘性注意你的名字,然後你在上面放一個箭頭指向綠色的沙發,然後你完成你的惡作劇,然後我的粘滯便箋不變,我的名字指向紅色的沙發。你創造了我無法觸及的粘滯便箋。

當你將一個新物體塞進t1中時,你並沒有銷燬舊物體,因爲你沒有授權。你只是把它推到一邊,並創建一個新的,除了你以外,沒有人可以訪問。

這條線:

t1 = new Test(999); 

不刪除舊的T1。您只需創建一個僅在方法本地的新t1,在方法結束後進行垃圾回收。使用這一行,您沒有更改傳入的參數,您創建了一個具有相同名稱的新變量。