2013-05-16 61 views
1

下面是我在JAVA中幾乎沒有疑問的代碼,沒有通過引用或通過地址傳遞。那麼爲什麼調用方法後輸出會發生變化?還想知道方法調用後JAVA的內部機制?調用函數並將對象作爲參數傳遞給它時,JAVA的行爲是什麼?

class Language 
{ 
    String languageID; 
    String name; 

    public Language(){} 

    public Language(String id, String name) 
    { 
     this.languageID = id; 
     this.name = name; 
    } 
    @Override 
    public String toString() { 
     return "Language id-->" + languageID + " Name-->" + name; 
    } 
} 

public class SwapDemo { 
    public static void swap() 
    { 
     int a = 10, b= 5; 
     System.out.println("Before Swap : A-"+a+" B-"+b); 
     a = a+b; 
     b = a-b; 
     a = a-b; 
     System.out.println("After Swap : A-"+a+" B-"+b); 
     a = a^b; 
     b = a^b; 
     a = a^b; 
     System.out.println("After Swap : A-"+a+" B-"+b); 
    } 

    public static void swap(Language e1, Language e2) 
    { 
     Language temp = new Language(); 
     temp = e1; 
     e1 = e2; 
     e2 = temp; 
    } 

    public static Language method(Language addit) 
    { 
     addit.name = "C++"; 
     addit = new Language(); 
     addit.name = "Harshal"; 
     return addit; 
    } 

    public static void main(String[] args) { 
     Language l1 = new Language("1", "C"); 
     Language l2 = new Language("2", "Java"); 

     System.out.println("Before swap of employees"); 
     System.out.println("Language 1-----> "+l1.toString()); 
     System.out.println("Language 2-----> "+l2.toString()); 

     swap(l1, l2); 
     System.out.println("After swap of employees"); 
     System.out.println("Language 1-----> "+l1.toString()); 
     System.out.println("Language 2-----> "+l2.toString()); 

     Language t = method(l1); 
     System.out.println("Changing "+ l1.name); 
     System.out.println("Changing "+ t.name); 
    } 
} 
+0

其實答案已經在這裏:http://stackoverflow.com/questions/40480/is-java-pass-by-reference?rq=1 – Woody

回答

0

Java是通過價值。它將參考的副本傳遞給方法。因此,這意味着:

List<String> l = new ArrayList<String>(); 
someMethod(l); 

一些方法剛剛通過l的副本 - 這是在堆上一個ArrayList的引用。

public void someMethod(List<String> aList) { 
    aList.add("Foo"); 
} 

的someMethod可以添加的東西到列表中,因爲在同一個對象作爲主叫範圍「L」本地參考ALIST點。但是請注意:

public void someMethod(List<String> aList) { 
    aList = new LinkedList<String>(); 
} 

對來電者沒有影響,這一切確實是使當地varaible「ALIST」點上堆不同的對象。請記住,aList是我們稱之爲方法的引用的副本,因此它們在重新分配之後都會引用相同的堆對象。

0

Figure

我解釋以下行,這將清除您的疑問。我假設你知道一堆關於堆和堆棧的節奏。

 Language t = method(l1); 
     System.out.println("Changing "+ l1.name); 
     System.out.println("Changing "+ t.name); 

這裏你逝去的「L1」對象要傳遞參考對象的方法。 REFERENCE是一種將用於識別物體的手柄HEAP SPACE

考慮,

A a =new A(); 

這裏將會包含什麼?顯然某些地址指向新創建的對象

所以當你傳遞一個對象給你的方法時你是傳遞一個對象所在的內存位置的引用。但是如果你嘗試像對待swap(l1,l2)方法那樣嘗試將對象更改爲某個其他對象,則內部方法會失敗,因爲您正在更改地址值,而不是實際對象

因此,語句addit.name =「C++」將更改駐留在addit指向的內存位置的對象的內容。因此這裏原始對象已被修改。希望這清楚你的第一個疑問。

關於你的第二個疑問,一個對象是生活在它的範圍內。只要方法調用獲得,那麼在該方法中分配的所有變量都有資格被垃圾收集。但是,在這裏你正在做什麼,你正在從方法返回對象的引用。所以對象不會被垃圾收集,因爲它有指向它的有效引用。因此在第二個輸出中它會打印新的值。希望這有助於理解輸出。

0

該問題的前提是有缺陷的。你不能用Java傳遞一個對象。 Java中唯一的類型是基元類型和引用類型,因此唯一的值是基元和引用。 「對象」不是值,並且不能被傳遞。對象只能通過指向它們的引用進行操作。在你的代碼中,l1,l2等都是引用。

相關問題