2011-12-23 50 views
1

這是我在StackOverflow的第一個問題。這是有問題的代碼:爲什麼這一個變量受到影響?

public class ListStuff { 
    public static void main(String [] args) { 

    String[] randomNames = {"Herbie", "Jaco", "Pat", "Michael"};   
    String[] reversedNames = revertNames(randomNames); 

    for (int i = 0; i < reversedNames.length; i++) { 
     System.out.println(reversedNames[i]); 
    } 
    } 

    public static String[] revertNames(String[] s) { 

    for (int i = 0; i < s.length/2; i++) { 
     String tmp = s[s.length - 1 - i]; 
     s[s.length - 1 - i] = s[i]; 
     s[i] = tmp; 
    } 

    return s; 
    } 
} 

此代碼運行正常和reversedNames可變打印爲恢復;沒有抱怨。但是,我的主要擔心是,當我執行String[] reversedNames = revertNames(randomNames);時,變量randomNames也會恢復。我在任何地方都沒有改變randomNames變量與randomNames = blabla;,所以我不明白爲什麼該變量不斷變爲自己的恢復版本,即使我只是將它作爲參數傳遞。

我已經編程了大約一年,而且我對變量範圍的瞭解非常有限。任何人都可以將我指向正確的方向嗎?

回答

3

這是因爲您通過引用而不是按值傳遞數組。實質上,這意味着reversedNames陣列仍然指向randomNames陣列,因此更改一個會改變另一個陣列。

這裏是變量的示意圖:

最初:

randomNames 

當我們進入revertNames功能:

randomNames <-------- s 

s陣列仍然指向回randomNames陣!因此,當我們更改s時,我們也更改了randomNames

當我們離開的功能:

randomNames <--------- s <--------- reversedNames 

因此,reversedNamesrandomNames。該功能完成後調用

後:

randomNames <--------- reversedNames 

雖然s陣列已經消失,reversedNames仍然指向randomNames

要解決此問題,創建一個臨時變量的revertNames函數內部:

public static String[] revertNames(String[] oldarray) { 
    // Create temporary array to avoid affecting original array 
    String[] s = oldarray.clone(); 
    ... 
+0

爲什麼downvote? – mc10 2011-12-23 22:48:46

+0

哇。有史以來最快的反應,偉大的阿夫斯傢伙,我會研究這個和變化=) – user1114051 2011-12-23 22:54:05

+0

我改變了我的投票現在...最初的反應沒有提供任何洞察力的問題。 +1 – 2011-12-23 23:04:09

7

數組在Java中的引用類型。這意味着當您將數組傳遞給revertNames方法時,該方法內的任何更改都會在外面看到。既然你是與此代碼更改裏面revertNames數組參數s

String tmp = s[s.length - 1 - i]; 
s[s.length - 1 - i] = s[i]; 
s[i] = tmp; 

這是代替s通過原始數組randomNames也是在這個過程中改變。

1

在revertNames的內部,你有一個變量s,這是一個對象的引用,它是一個數組。實際的數組是數組randomNames。所以你確實正在改變源數組中的值。如果您使用數組,請使用數組。copy()你可以得到一個獨立的數組來工作 - 副本將指向與原始數組相同的字符串,但是由於字符串是不可變的,所以這是安全的。

0

您可以使用:StringBuffer的:反轉()

一些東西像:

public class t { 
    public static void main(String [] args) { 

    String[] randomNames = {"Herbie", "Jaco", "Pat", "Michael"};   
    StringBuffer rev; 
    for (int i = 0; i < randomNames.length; i++) 
    { 
     rev=new StringBuffer(randomNames[i]); 
     System.out.println(rev.reverse().toString()); 
    } 
    } 
} 
0

陣列中的Java是引用類型,也就是說,如果你聲明

String[] randomNames; 

你聲明一個局部變量,它保存對一個字符串數組的對象的引用。

聲明

String[] otherNames = randomNames; 

將變量randomNames的內容複製到變量otherNames,但內容只是一個參考。也就是說,這個語句會導致otherNames和randomNames引用同一個數組對象。

同樣的,當你傳遞一個String[]作爲方法的參數發生。即,在revertNames局部變量s,並且在main局部變量randomNames將包含相同的附圖標記的,即是指相同的陣列對象。也就是說,雖然srandomNames都會顯示該數組對象的狀態。

嚴格地說,這與範圍界定無關,因爲變量randomNames未被修改(即它仍指向相同的數組)。被修改的是它引用的對象。

相關問題