Java: Why does this swap method not work?

Viewed 32877

I have the following code:

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

I expect it to print a=2 b=1, but it prints the opposite. So obviously the swap method doesn't swap a and b values. Why?

10 Answers

This doesn't have anything to do with immutability of integers; it has to do with the fact that Java is Pass-by-Value, Dammit! (Not annoyed, just the title of the article :p )

To sum up: You can't really make a swap method in Java. You just have to do the swap yourself, wherever you need it; which is just three lines of code anyways, so shouldn't be that much of a problem :)

    Thing tmp = a;
    a = b;
    b = tmp;

Everything in Java is passed by value and the values of variables are always primitives or references to object.

If you want to implement a swap method for Integer objects, you have to wrap the values into an array (or ArrayList) and swap inside the array. Here's an adaptation of your code:

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

(Just added this answer because Svish mentioned, that "You can't really make a swap method in Java" fg)

As Svish and others pointed out it it's call by value, not by reference in Java. Since you have no pointers in Java you need some kind of holder object to really swap values this way. For example:

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

}

You would need to pass the parameters by reference, which it's not possible in java. Also Integers are inmutables, so you cannot exchange the values as you don't have a setValue method.

Integer are immutable - you can't change their values. The swapping that occurs inside the swap function is to the references, not the values.

You would need to return both references in an array to achieve what you want

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

If Integer had a setValue method, you could do something like this.

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

But it doesn't - so to achieve what you want, return an array.

As all the guys mentioned its a Pass-By-Value thing.

Just liked to add: you can use this method of swapping GLOBAL integers.

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

It eliminates the use of another variable, and its just cooler :)

Using the XOR operator is a very bad idea:

First, it is far less readable. Second, there were times when this was faster but nowadays the opposite is the case. See

Wikipedia

for reference.

Related