2010-01-11 14 views
22

Tengo el siguiente código:Java: ¿Por qué este método de intercambio no funciona?

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); 
    } 
} 

espero que imprime a = 2 b = 1, pero se imprime lo contrario. Entonces, obviamente, el método de intercambio no intercambia los valores a y b. ¿Por qué?

+8

favor refiérase diferencia entre la llamada por valor y llamada por referencia. –

+1

En el intercambio de métodos está pasando 'valores' del objeto y no la referencia al objeto real, lo que sea que haga dentro del método de intercambio no tendrá efecto en las variables a y b. –

Respuesta

42

Esto no tiene nada que ver con la inmutabilidad de los números enteros; que tiene que ver con el hecho de que Java is Pass-by-Value, Dammit!(No es molesto, sólo el título del artículo: p)

En resumen: Realmente no se puede realizar un método de intercambio en Java. Solo tienes que hacer el cambio, donde sea que lo necesites; el cual está a sólo tres líneas de código de todos modos, por lo que no debería ser un gran problema :)

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

¿Por qué votar abajo? ¿He entendido mal algo? – Svish

+0

Pero si el entero era mutable y tenía, por ejemplo, un campo setValue, el intercambio de valores al llamar a setValue sería un cambio visible. Por lo tanto, tiene algo que ver con la mutabilidad en el sentido de que aún podría tener un método nulo que lograra el resultado que desea el autor. –

+7

Pero en realidad no habrías intercambiado los enteros, lo que parece ser el objetivo. Si tuviera un estacionamiento con dos autos y luego hiciera que el primer automóvil se viera exactamente como el segundo y el segundo exactamente como el primer automóvil, ¿habría cambiado los autos? Realmente no. Hubiera hecho * mucho * trabajo para que pareciera así. – Svish

0

Entero son inmutables: no puede cambiar sus valores. El intercambio que ocurre dentro de la función de intercambio es a las referencias, no a los valores.

Usted tendría que volver ambas referencias en una matriz para lograr lo que quiere

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); 
} 

Si entero tenía un método setValue, se podría hacer algo como esto.

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

Pero no es así, así que para lograr lo que desea, devuelva una matriz.

+8

La inmutabilidad entera no es el problema aquí. – Svish

6

Todo en Java se pasa por valor y los valores de las variables son siempre las primitivas o referencias a objeto.

1

Debería pasar los parámetros por referencia, lo cual no es posible en java. Además, los enteros son inmutables, por lo que no puede intercambiar los valores ya que no tiene un método setValue.

2

Como Svish y otros señalaron que es llamada por valor, no por referencia en Java. Como no tiene punteros en Java, necesita algún tipo de objeto contenedor para intercambiar valores de esta manera. Por ejemplo:

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. Usar AtomicReference probablemente no tenga mucho sentido para ti, ya que es un idioma de simultaneidad. Escriba su propio titular si no necesita un comportamiento seguro de subprocesos. – yawn

+0

"no tiene punteros en Java". Supongo que Java tiene el concepto de punteros, pero no está a disposición de los programadores. –

+2

Por lo que sé, tiene punteros en Java.Simplemente se llaman referencias y no se pueden manipular como se puede en varios otros idiomas en varios grados. – Svish

2

Si se desea implementar un método de intercambio de objetos Integer, hay que envolver los valores en una matriz (o ArrayList) y de intercambio dentro de la matriz. Aquí está una adaptación de su código:

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]); 
    } 
} 

(acaba de añadir esta respuesta porque Svish mencionado, que "realmente no se puede realizar un método de intercambio en Java"fg)

0

Como todo el los chicos mencionaron que es algo que pasa por alto.

Me gustó agregar: puede utilizar este método para intercambiar enteros GLOBALES.

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

Se elimina el uso de otra variable, y es sólo más fresco :)

+2

. Puede ser genial, pero no es muy legible. –

+0

Versión genial de swap, sin variables adicionales, complicado y bueno para preguntar a los estudiantes cómo hacerlo ;-), pero ... no funciona en Java :-(. ¿O es? – WildWezyr

+0

@WildWezyr ¿cómo no? Tenga cuidado que a y b deberían ser globales aquí, de lo contrario necesitarás usar los métodos mencionados por los chicos que están arriba de – medopal

0

usando el operador XOR es una muy mala idea:

En primer lugar, es mucho menos legible. En segundo lugar, hubo momentos en que esto fue más rápido, pero hoy en día sucede lo contrario. Ver

Wikipedia

de referencia.

+2

FYI, porque SO se reorganiza las respuestas cuando se ponen arriba/abajo votaron que generalmente es una buena idea usar el enlace "agregar comentario" para agregar un comentario a la respuesta a la que se refiere en lugar de escribir el comentario en una nueva respuesta. Hace que sea más fácil averiguar qué estás comentando – Fredrik

0

código 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); 

    } 
} 

Salida:

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

El uso del escáner:

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); 
}  
} 
Cuestiones relacionadas