37

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?

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
witzar
  • 760
  • 1
  • 7
  • 12
  • 8
    Please refer difference between call by value and call by reference. – Ravi Gupta Jan 11 '10 at 11:45
  • 1
    In method swap you are passing 'values' of the object and not the reference to actual object, whatever you do inside swap method will have no effect on variable a and b. – Ravi Gupta Jan 11 '10 at 12:18

10 Answers10

55

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
  • 152,914
  • 173
  • 462
  • 620
  • 4
    Why the down-vote? Have I misunderstood something? – Svish Jan 11 '10 at 11:58
  • 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 Jan 11 '10 at 12:01
  • 9
    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 Jan 11 '10 at 12:06
  • 1
    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 Jan 11 '10 at 12:14
  • 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 Jan 11 '10 at 12:25
  • +1 because of the article title :) – mohdajami Jan 11 '10 at 13:00
  • @medopal: Thank you. Not my article though :p – Svish Jan 11 '10 at 13:16
  • 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 Jan 11 '10 at 22:46
  • You cannot swap in Java because all you have are "pointers" (if you look at C/C++ family languages). You cannot pass the address of the memory location where a and b have their values and modify them in place – Ghita Nov 15 '12 at 20:57
  • 3
    No, the reason you can't swap in Java is because you have _no_ pointers. Pointers are what enables a swap method in c++. You can sort of swap the values of two object's fields, but you can't have a generic swap function. And even then, it's just doing what is said in the cars example above. – Mitchell Carroll May 06 '15 at 20:50
10

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

Ravi Gupta
  • 4,468
  • 12
  • 54
  • 85
4

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 Dolk
  • 113,398
  • 19
  • 180
  • 268
3

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
  • 8,014
  • 7
  • 29
  • 34
  • 1
    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 Jan 11 '10 at 12:01
  • "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 Jan 11 '10 at 12:22
  • 2
    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 Jan 11 '10 at 12:30
  • 1
    All you have in Java are pointers. If you would have references (for example to those pointers) you could modify the values those pointers contain – Ghita Nov 15 '12 at 20:59
1

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
  • 3,582
  • 1
  • 25
  • 26
0

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.

Robert Christie
  • 20,177
  • 8
  • 42
  • 37
0

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

mohdajami
  • 9,604
  • 3
  • 32
  • 53
  • 3
    It may be cool, but it is not very readable. – mR_fr0g Jan 11 '10 at 13:12
  • 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 Jan 11 '10 at 13:15
  • @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 – mohdajami Jan 11 '10 at 13:17
  • 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 Jan 11 '10 at 13:20
  • @medopal: If I print variables a&b after executing your method private void swap (Integer a, Integer b){...} they are still unswapped (unchanged as a side-effect of your swap method). Provided statement a ^= b is just a shorthand of a = a ^ b, so it is just an variable assignment, which is not working in Java for swap method. – WildWezyr Jan 11 '10 at 13:27
  • 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. – mohdajami Jan 11 '10 at 13:30
  • @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 Jan 11 '10 at 14:14
0

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.

helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • 2
    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 Jan 12 '10 at 13:37
0

Java code:

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

    }
}

Output:

trial.n1 = 2
trial.n2 = 3
trial.n1 = 3
trial.n2 = 2
Daniel Vaughn
  • 13
  • 2
  • 7
0

Using Scanner:

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