2015-04-30 2 views
0

По какой-то причине мой метод perfectShuffle (int [] values) мутирует передаваемый в него параметр, пожалуйста, скажите мне, почему это ... Это не имеет никакого смысла для меня, потому что Java - это программирование «Pass by Value» язык.Параметр метода 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); 
Смежные вопросы