tags:

views:

629

answers:

9

Hi. 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?

+1  A: 
Robert Christie
Integer immutability is not the issue here.
Svish
+28  A: 

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;
Svish
Why the down-vote? Have I misunderstood something?
Svish
But if Integer was mutable and had for example a setValue field, swapping the values by calling the setValue would be a visible change. So it does have something to do with mutability in that you could still have a void method that achieved the result the auther wants.
Robert Christie
But you wouldn't have actually swapped the integers, which seems to be the goal. If I have a parking lot with two cars and then made the first car look exactly like the second car and the second car exactly like the first car, would I have swapped the cars? Not really. I would just have done *a lot* of work to make it appear that way.
Svish
Sometimes encapsulated swap methods are required - obviously not in this case. The use of arrays to return multiple values is a common pattern for this type of problem.
Robert Christie
Hm, but if the swap method returns an array, wouldn't you just have to do the swapping manually afterwards anyways? Like in this case, you would have to do `Integer[] r = swap(a, b); a = r[0]; b = r[1];`. And I mean... just doing the swap manually right there is both shorter and more readable. Unless you had them in an array in the first place, passed that in and got back a new array with the values swapped. But that would be something quite different.
Svish
+1 because of the article title :)
medopal
@medopal: Thank you. Not my article though :p
Svish
Thanks for the ref to my article! Glad you found it useful (and liked the article title ;). You're correct that this doesn't have anything to do with immutability and everything to do with Java being pass-by-value.
Scott Stanchfield
@Scott: Thank you for the article!
Svish
+6  A: 

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

Ravi Gupta
+2  A: 

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.

ggf31416
+2  A: 

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

}
yawn
P.S. Using AtomicReference makes probably not much sense for you since it's a concurrency idiom. Write your own holder if you do not need thread-safe behavior.
yawn
"you have no pointers in Java". I guess Java has the concept of pointers but its not at the disposal of programmers to use.
Ravi Gupta
As far as I know, you have pointers in Java. They are just called references and you can't manipulate them as you can in various other languages in various degrees.
Svish
+1  A: 

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

Andreas_D
A: 

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

medopal
It may be cool, but it is not very readable.
mR_fr0g
Cool version of swap - without extra variable, tricky and good for asking students how to do it ;-), but... it is not working in Java :-(. Or is it?
WildWezyr
@WildWezyr how not? be careful that a and b should be global here, otherwise you will need to use the methods mentioned by the guys above
medopal
a ^= b is the same as a = a ^ b. It effects in assigning value of expression (a ^ b) to local variable a. Other two assignments also affect only local variables (inside swap method), so this cool trick is not working.
witzar
WildWezyr
again, it does not fix the Pass By Value issue, its just another version of the classic swap. If you want to try it, use global variables, OR send it an array of two integers.
medopal
@medopal - why then you use misleading signature of your swap method? if it can only work on globals - it should have no arguments... until you fix it - current version of your code will not work, but someone could read it and think that it works :-(.
WildWezyr
have edit it, hope you are happier now. thanks for the down vote without saying why
medopal
A: 

Well, it actually is possible using AtomicInteger (which is mutable).

import java.util.concurrent.atomic.AtomicInteger;

public class Test {
    private static void swap(AtomicInteger a, AtomicInteger b) {
        int val = a.get();
        a.set(b.get());
        b.set(val);
    }

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

        swap(a, b);

        System.out.println("a: " + a + " b: " + b);
    }
}
Helper Method
A: 

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.

Helper Method
FYI, because SO reshuffles answers when they get up/down voted it is usually a good idea to use the "add comment" link to add a comment to the answer you are referring to rather then writing the comment in a new answer. Makes it easier to figure out what you are commenting.
Fredrik