2010-01-11 5 views
22

У меня есть следующий код:Java: Почему этот метод обмена не работает?

public class Main { 

    static void swap (Integer x, Integer y) { 
     Integer t = x; 
     x = y; 
     y = t; 
    } 

    public static void main(String[] args) { 
     Integer a = 1; 
     Integer b = 2; 
     swap(a, b); 
     System.out.println("a=" + a + " b=" + b); 
    } 
} 

я ожидаю, что это напечатать = 2 Ь = 1, но он печатает обратное. Таким образом, очевидно, что метод подкачки не меняет значения a и b. Зачем?

+8

Пожалуйста, обратитесь разницу между вызовом по значению и вызов по ссылке. –

+1

В методе swap вы передаете «значения» объекта, а не ссылку на фактический объект, независимо от того, что вы делаете внутри метода swap, не будет влиять на переменные a и b. –

ответ

42

Это не имеет никакого отношения к неизменности целых чисел; это связано с тем фактом, что Java is Pass-by-Value, Dammit!(не раздражен, просто название статьи: р)

Подводя итог: Вы не можете действительно сделать метод подкачки в Java. Вам просто нужно сделать своп самостоятельно, где бы вы ни нуждались; который находится всего три строки кода в любом случае, так не должно быть, что большая проблема :)

Thing tmp = a; 
    a = b; 
    b = tmp; 
+4

Почему проголосовали? Я что-то неправильно понял? – Svish

+0

Но если Integer был изменен и имел, например, поле setValue, то замена значений путем вызова setValue была бы видимым изменением. Таким образом, он имеет какое-то отношение к изменчивости в том, что вы все еще можете использовать метод void, который достиг результата, который хочет получить автор. –

+7

Но вы бы не поменяли целые числа, что, кажется, является целью. Если у меня есть автостоянка с двумя автомобилями, а затем первый автомобиль выглядит точно так же, как второй автомобиль, а второй автомобиль точно так же, как первый автомобиль, я бы поменял автомобили? На самом деле, нет. Я бы просто сделал * много работы, чтобы он казался таким. – Svish

0

Целое слово неизменное - вы не можете изменить свои значения. Перестановка, которая происходит внутри функции свопинга, относится к ссылкам, а не значениям.

Вы должны были бы вернуть обе ссылки в массив, чтобы достичь того, чего вы хотите

static Integer[] swap(Integer a, Integer b) { 
    return new Integer[]{b, a}; 
} 

public static void main(String[] args) { 
    Integer a = 1; 
    Integer b = 2; 

    Integer[] intArray = swap(a, b); 

    a = intArray[0]; 
    b = intArray[1]; 

    System.out.println("a=" + a + " b=" + b); 
} 

Если Integer был метод SetValue, вы могли бы сделать что-то вроде этого.

static void swap(Integer a, Integer b) { 
    int temp = a.intValue(); 
    a.setValue(b.intValue()); 
    b.setValue(temp); 
} 

Но это не так, чтобы достичь того, чего вы хотите, верните массив.

+8

Целочисленная неизменность здесь не проблема. – Svish

6

Все в Java передается по значению, и значения переменных всегда примитивы или ссылки на объект.

1

Вам нужно будет передать параметры по ссылке, что невозможно в java. Также Integer являются inmutables, поэтому вы не можете обменивать значения, поскольку у вас нет метода setValue.

2

Поскольку Svish и другие указали, что это вызов по значению, а не по ссылке на Java. Поскольку у вас нет указателей на Java, вам нужен какой-то объект-держатель, чтобы действительно менять значения таким образом. Например:

static void swap(AtomicReference<Integer> a, AtomicReference<Integer> b) { 

    Integer c = a.get(); 
    a.set(b.get()); 
    b.set(c); 

} 

public static void main(String[] args) { 

    AtomicReference<Integer> a = new AtomicReference<Integer>(1); 
    AtomicReference<Integer> b = new AtomicReference<Integer>(2); 

    System.out.println("a = " + a); 
    System.out.println("b = " + b); 

    swap(a, b); 

    System.out.println("a = " + a); 
    System.out.println("b = " + b); 

} 
+1

P.S. Использование AtomicReference, вероятно, не имеет большого смысла для вас, поскольку это идиома параллельности. Создайте свой собственный держатель, если вам не нужны поточно-безопасные действия. – yawn

+0

«У вас нет указателей на Java». Я предполагаю, что у Java есть концепция указателей, но она не в распоряжении программистов. –

+2

Насколько я знаю, у вас есть указатели на Java.Они просто называются ссылками, и вы не можете манипулировать ими, как можете, на разных других языках в разной степени. – Svish

2

Если вы хотите реализовать метод подкачки для объектов Integer, вы должны обернуть значения в массив (или ArrayList) и обмен внутри массива. Вот адаптация кода:

public class Main { 

    static void swap (Integer[] values) { 
     if ((values == null) || (values.length != 2)) { 
      throw new IllegalArgumentException("Requires an array with exact two values"); 
     } 

     Integer t = values[0]; 
     values[0] = values[1]; 
     values[1] = t; 
    } 

    public static void main(String[] args) { 
     Integer a = 1; 
     Integer b = 2; 
     Integer[] integers= new Integer[]{a,b}; 
     swap(integers); 
     System.out.println("a=" + integers[0] + " b=" + integers[1]); 
    } 
} 

(Просто добавили этот ответ, потому что Svish упоминалось, что «Вы не можете действительно сделать метод подкачки в Java»Ф.Г.)

0

Как все ребята упомянули о своей вещи «Постепенное значение».

Просто понравилось: вы можете использовать этот способ замены GLOBAL-целых чисел.

private void swap(){ 
    a ^= b; 
    b ^= a; 
    a ^= b; 
} 

Это исключает использование другой переменной, и его просто круче :)

+2

Это может быть классно, но это не очень читаемо. –

+0

Прохладная версия swap - без лишней переменной, сложная и хорошая для того, чтобы спросить студентов, как это сделать ;-), но ... она не работает в Java :-(Или это? – WildWezyr

+0

@WildWezyr как не быть осторожным что a и b должны быть глобальными здесь, иначе вам нужно будет использовать методы, упомянутые ребятами выше – medopal

0

Используя оператор XOR очень плохая идея:

Во-первых, это гораздо менее читабельным. Во-вторых, были времена, когда это было быстрее, но в настоящее время наоборот. См

Wikipedia

для справки.

+2

FYI, потому что SO перестановки ответы, когда они поднимаются/опускаются, обычно рекомендуется использовать ссылку «добавить комментарий», чтобы добавить комментарий к ответу, на который вы ссылаетесь, вместо того, чтобы писать комментарий в новом ответе. Легче понять, что вы комментируете. – Fredrik

0

код Java:

class swap { 

    int n1; 
    int n2; 
    int n3; 

    void valueSwap() { 
     n3 = n1; 
     n1 = n2; 
     n2 = n3; 
    } 

    public static void main(String[] arguments) { 

     Swap trial = new Swap(); 
     trial.n1 = 2; 
     trial.n2 = 3; 

     System.out.println("trial.n1 = " + trial.n1); 
     System.out.println("trial.n2 = " + trial.n2); 

     trial.valueSwap(); 

     System.out.println("trial.n1 = " + trial.n1); 
     System.out.println("trial.n2 = " + trial.n2); 

    } 
} 

Выход:

trial.n1 = 2 
trial.n2 = 3 
trial.n1 = 3 
trial.n2 = 2 
0

Использование сканера:

import java.util.*; 
public class Swap { 
public static void main(String[] args){ 
    int i,temp,Num1,Num2; 
    Scanner sc=new Scanner(System.in); 
    System.out.println("Enter Number1 and Number2"); 
    Num1=sc.nextInt(); 
    Num2=sc.nextInt(); 
    System.out.println("Before Swapping Num1="+Num1+" Num2="+Num2); 
    temp=Num1; 
    Num1=Num2; 
    Num2=temp; 
    System.out.println("After Swapping Num1="+Num1+" Num2="+Num2); 
}  
} 
Смежные вопросы