2015-04-30 49 views
0

出於某種原因,我的方法perfectShuffle(int []值)正在變異傳遞給它的參數,請告訴我爲什麼這是...這對我來說沒有意義,因爲Java是一種「通過價值傳遞」編程語言。Java方法參數是否被突變?

public class Shuffler { 

    /** 
    * The number of consecutive shuffle steps to be performed in each call to 
    * each sorting procedure. 
    */ 
    private static final int SHUFFLE_COUNT = 4; 

    /** 
    * The number of values to shuffle. 
    */ 
    private static final int VALUE_COUNT = 5; 

    /** 
    * Tests shuffling methods. 
    * 
    * @param args 
    *   is not used. 
    */ 
    public static void main(String[] args) { 
     System.out.println("Results of " + SHUFFLE_COUNT 
       + " consecutive perfect shuffles:"); 
     int[] values1 = new int[VALUE_COUNT]; 
     for (int i = 0; i < values1.length; i++) { 
      values1[i] = i; 
     } 
     for (int j = 1; j <= SHUFFLE_COUNT; j++) { 
      perfectShuffle(values1); 
      System.out.print(" " + j + ":"); 
      for (int k = 0; k < values1.length; k++) { 
       System.out.print(" " + values1[k]); 
      } 
      System.out.println(); 
     } 
     System.out.println(); 

     System.out.println("Results of " + SHUFFLE_COUNT 
       + " consecutive efficient selection shuffles:"); 
     int[] values2 = new int[VALUE_COUNT]; 
     for (int i = 0; i < values2.length; i++) { 
      values2[i] = i; 
     } 
     for (int j = 1; j <= SHUFFLE_COUNT; j++) { 
      values2 = selectionShuffle(values2); 
      System.out.print(" " + j + ":"); 
      for (int k = 0; k < values2.length; k++) { 
       System.out.print(" " + values2[k]); 
      } 
      System.out.println(); 
     } 
     System.out.println(); 
    } 

    /** 
    * Apply a "perfect shuffle" to the argument. The perfect shuffle algorithm 
    * splits the deck in half, then interleaves the cards in one half with the 
    * cards in the other. 
    * 
    * @param values 
    *   is an array of integers simulating cards to be shuffled. 
    */ 
    public static void perfectShuffle(int[] values) { 
     int max = (values.length+1)/2; 
     int[] shuffled = new int[values.length]; 
     int k = 0; 
     for (int j = 0; j < (values.length); j++) { 
      shuffled[k] = values[j]; 
      k++; 
     } 
     k = 0; 
     for (int j = 0; j < max; j++) { 
      values[k] = shuffled[j]; 
      k += 2; 
     } 
     k=1; 
     for (int j = max+1; j < values.length; j++){ 
      values[k] = shuffled[j]; 
      k+=2; 
     } 
    } 

    /** 
    * Apply an "efficient selection shuffle" to the argument. The selection 
    * shuffle algorithm conceptually maintains two sequences of cards: the 
    * selected cards (initially empty) and the not-yet-selected cards 
    * (initially the entire deck). It repeatedly does the following until all 
    * cards have been selected: randomly remove a card from those not yet 
    * selected and add it to the selected cards. An efficient version of this 
    * algorithm makes use of arrays to avoid searching for an as-yet-unselected 
    * card. 
    * 
    * @param values 
    *   is an array of integers simulating cards to be shuffled. 
    */ 
    public static int[] selectionShuffle(int[] values) { 
     Random rand = new Random(); 
     for (int k = values.length - 1; k > 0; k--) { 
      int r = rand.nextInt((k) + 1); 
      int transfer = values[k]; 
      values[k] = values[r]; 
      values[r] = transfer; 
     } 
     return values; 
    } 


} 
+3

你需要做數組的一個副本。 – screenmutt

+0

引用是按值傳遞的。這是預期的行爲。 –

+0

「Java是」通過引用傳遞「還是」按值傳遞「? http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value – CubeJockey

回答

7

實際上,正在傳遞的值是參考陣列,從而所述陣列上操作的直接變異在呼叫者的數組的內容。使用陣列的副本以確保不變性。

+0

你能否也請解釋爲什麼數組在原始數據類型中不這樣做。 –

+0

數組是一個'Array'對象,並作爲參考與堆棧中的任何其他類型一起傳遞。原始類型只是一個立即值,將值複製到堆棧中。這個「看起來」並不是「String」或「BigInteger」類型的情況,因爲這些類型是顯式不可變的,並且對這些類型的任何操作實際上都會創建一個副本。 – PaulProgrammer

2

Java實際上是通過對該值的引用。您會看到一個side-effect

嘗試複製數組。

int[] myValues = new int[values.length] 
System.arraycopy(values, 0, myValues, 0, values.length); 

int[] myValues = Arrays.copyOf(values, values.length); 

Code Source

1

你的方法傳遞給數組的引用。所以你的方法正在改變原始數組。

你需要做數組的副本:

int[] copy = Arrays.copyOf(original, original.length);