5

Can we swap two numbers in Java using pass by reference or call by reference? Recently when I came across swapping two numbers in Java I wrote

class Swap{
    int a,b;
    void getNos(){
        System.out.println("input nos");
        a = scan.nextInt();
        b = scan.nextInt(); // where scan is object of scanner class
    }
    void swap(){
        int temp;
        temp = this.a;
        this.a = thisb;
        this.b = this.a;
    }
}

In the main method I call the above mentioned methods and take two integers a,b and then using the second method I swap the two numbers, but relative to the object itself....

Does this program or logic come under pass by reference? And is this correct solution?

A.H.
  • 63,967
  • 15
  • 92
  • 126
thewhitetulip
  • 3,235
  • 3
  • 21
  • 26
  • 2
    Java does not have "call by reference". –  Feb 20 '12 at 12:58
  • java doesn't have pass by ref but isn't it a reference passed when you pass an object of a class to a method? i am having doubts now on this topic.... when i read Core java fundamentals by Sun, the book stated thet when you create an object your object code is actually a pointer analogous thing wrt C++, i.e. it is a reference variable – thewhitetulip Feb 20 '12 at 13:07

2 Answers2

6

Yes and no. Java never passes by reference, and your way is one workaround. But yet you create a class just to swap two integers. Instead, you can create an int wrapper and use pass it, this way the integer may be separated when not needed:

public class IntWrapper {
    public int value;
}

// Somewhere else
public void swap(IntWrapper a, IntWrapper b) {
    int temp = a.value;
    a.value = b.value;
    b.value = temp;
}

As the comments show, I might not have been clear enough, so let me elaborate a little bit.

What does passing by reference mean? It means that when you pass an argument to the method, you can change the original argument itself inside this method.

For example, if Java was pass-by-reference, the following code will print out x = 1:

public class Example {
    private static void bar(int y) {
        y = 10;
    }
    public static void main(String[] args) {
        int x = 1;
        bar(x);
        System.out.println("x = " + x);
    }
}

But as we know, it prints 0, since the argument passed to the bar method is a copy of the original x, and any assignment to it will not affect x.

The same goes with the following C program:

static void bar(int y) {
    y = 1;
}
int main(int argc, char * argc[]) {
    int x = 0;
    bar(x);
    printf("x = %d\n", x);
}

If we want to change the value of x, we will have to pass its reference (address), as in the following example, but even in this case, we will not pass the actual reference, but a copy of the reference, and by dereferencing it we will be able to modify the actual value of x. Yet, direct assignment to the reference will no change the reference itself, as it is passed by value:

static void bar(int &y) {
    *y = 1;
    y = NULL;
}
int main(int argc, char * argc[]) {
    int x = 0;
    int * px = &x;
    bar(px);
    printf("x = %d\n", x); // now it will print 1
    printf("px = %p\n", px); // this will still print the original address of x, not 0
}

So passing the address of the variable instead of the variable itself solves the problem in C. But in Java, since we don't have addresses, we need to wrap the variable when we want to assign to it. In case of only modifying the object, we don't have that problem, but again, if we want to assign to it, we have to wrap it, as in the first example. This apply not only for primitive, but also for objects, including those wrapper objects I've just mentioned. I will show it in one (longer) example:

public class Wrapper {
    int value;
    private static changeValue(Wrapper w) {
        w.value = 1;
    }
    private static assignWrapper(Wrapper w) {
        w = new Wrapper();
        w.value = 2;
    }
    public static void main(String[] args) {
        Wrapper wrapper = new Wrapper();
        wrapper.value = 0;
        changeValue(wrapper);
        System.out.println("wrapper.value = " + wrapper.value); 
        // will print wrapper.value = 1
        assignWrapper(w);
        System.out.println("wrapper.value = " + wrapper.value); 
        // will still print wrapper.value = 1
    }
}

Well, that's it, I hope I made it clear (and didn't make too much mistakes)

Peter O.
  • 32,158
  • 14
  • 82
  • 96
MByD
  • 135,866
  • 28
  • 264
  • 277
  • if i create and pass like you said, can it be loosely called call by reference or pass by reference? – thewhitetulip Feb 20 '12 at 13:09
  • 2
    I have never heard of this term. Java just don't pass by reference. Even if the reference (object reference) is passed, the reference cannot be changed in the method, only the obeject it references to. – MByD Feb 20 '12 at 13:11
  • so even if i pass a object it isn't pass by reference? right?? are you sure?? bcoz i have refered few books who say Heading is pass by reference, and they explain the object is passed to a method, so is it wrong?? – thewhitetulip Feb 20 '12 at 13:15
  • 3
    In Java you don't pass Objects, you pass references. Even `Object o1 = o2` is not handling an object but handling a reference. So `f(o1)` also passes the reference by value (which is not the same as pass by reference). In my experience anyone calling this mechanism incorrectly or offhand "pass by reference" either does not really know what he is talking about or tries to take a shortcut which works in some cases but not in other cases. – A.H. Feb 20 '12 at 13:28
  • 1
    If you were writing the exact code above in C++, you would define `swap()` as `void swap(IntWrapper *a, IntWrapper *b)`. So, in a sense, you are passing objects as reference. As Java hides the referencing/dereferencing process from you, however, Java people call this "pass by value", even though the "value" is in fact a reference! I find the terminology confusing too, so I focus more on how it works and less on what it is called. – Eser Aygün Feb 20 '12 at 13:33
  • 2
    @EserAygün: Even in C/C++ your suggestion would be "pass by value" because you pass the pointer, not an object. Only C++ would support real pass by reference with `swap(int &a, int &b)`; – A.H. Feb 20 '12 at 13:35
  • @A.H. Isn't it what Java does exactly when working with objects? `a` is a reference when you define it as `IntWrapper a`, right? And `swap()` accepts references rather than actual objects. So, it is the same thing without ampersands. Therefore, we are naming it after how it looks than how it works, actually. – Eser Aygün Feb 20 '12 at 14:03
  • in java complete reference, a notable book its given, pass by reference means passing object or the ref to the object :) again confusion!!! – thewhitetulip Feb 20 '12 at 14:06
  • 2
    @EserAygün: Two points: On the machine-code level it may be the same. But the terminology is not based on implementation details like that but on the visible effects in the language (here Java) itself. Second: If the language does not support pass by reference but supports some kind of pointer (in C) or some kind of reference type (Java), then _you_ as the user of the language can _simulate_ _some_ (not all) effects of PBR by using an indirection. This manual indirection is __incorrectly__ often named "pass by reference" - as kind of language shortcut. – A.H. Feb 20 '12 at 14:18
  • 1
    @A.H. I understand the second point and I agree. On the first point, I was not referring to implementation details but actual effects. _When working with objects_, PBR in C++ has the same effects as PBV (as everybody calls it) in Java. The only difference I can see is the notation. One could easily change the Java syntax and require `&` before reference types. Then how would you explain the difference? (I'm not trying to bug you by the way. Excuse me if I seem obstinate.) – Eser Aygün Feb 20 '12 at 14:35
  • 1
    @EserAygün: In C++ you omitt the caller side: When declaring `void swap(int &a, int &b);` the caller can do `int a=42, b=1; swap(a,b);` and that's it. The PBR machinery hides the details. No _visible_ intermediate steps/pointers. Doing this in Java by simply changing the syntax without changing the semantic, this is not possible. – A.H. Feb 20 '12 at 14:42
  • 1
    @A.H. `int` is not an object type. You can't pass primitive types by reference in Java. So, in my hypothetical language (Java with ampersands), it would be disallowed to define primitive arguments with `&`. Similarly, it would be disallowed to define object arguments _without_ `&` (as all objects must reside inside the heap). This hypothetical Java syntax would look like C++, work like C++, with the intrinsic restrictions of Java that I listed above. That's what I was trying to demonstrate. I need more space to discuss it further. Maybe I should write an article... – Eser Aygün Feb 20 '12 at 16:00
  • so java does not support call by reference and although an object in java is actually a reference, we can't say that a method that takes an object as a parameter as pass by reference... the first part is okay, but it must be okay for the later part.... after all the definition of reference doesn't always mean pointer as in C language, that statement simply says that call by reference, where in reference means object... so whats wrong?? – thewhitetulip Feb 20 '12 at 17:41
  • 1
    @EserAygün: primitives confuse the issue. Let's use any immutable object type, like `Integer` or `String` instead. In Java, `void swap(Integer a, Integer b); Integer a = new Integer(42), b = new Integer(1); swap(a,b);` cannot change the values of `a` and `b` in the calling scope. Same with the C++ pass by value: `void swap(Integer *a, Integer *b); Integer *a = new Integer(42), *b = new Integer(1); swap(a,b);` However, C++ pass-by-reference can: `void swap(Integer *&a, Integer *&b); Integer *a = new Integer(42), *b = new Integer(1); swap(a,b);` Nothing extra needs to be done at the call site. – newacct Feb 21 '12 at 12:01
  • @newacct Good argument! But now you are using pointer references (`Integer *&`). If Java had had pointers you could do the same: `swap(Pointer a, Pointer b); ...` In fact, you can implement a `Pointer` class easily and achieve the same effect. Again, I cannot see any difference between how C++ and Java handle object references. – Eser Aygün Feb 21 '12 at 12:41
  • @EserAygün: Java's "reference" is a pointer to an object (JLS 4.3.1 http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1). They are semantically equivalent to pointers in C/C++ (i.e. when you `new` you get a reference (pointer); you can assign one reference to another which copies the pointer). See http://javadude.com/articles/passbyvalue.htm C++ references are something different entirely. If you are arguing that Java references are like C++ references then that would imply that C++ pointers are semantically like C++ references. – newacct Feb 23 '12 at 10:48
  • @newacct In the tutorial of Alex Allain, he says "C++ references allow you to create a second name for the a variable that you can use to read or modify the original data stored in that variable." If this is true, can you (or he) tell me to which variable is `x` referring to in this case: `Integer &x = *(new Integer());` None! `x` is referring to an anonymous piece of memory, just as pointers do. So, yes, _when working with objects_ I think C++ pointers and C++ references are semantically identical. That's why I'm reluctant to use pass-by-value and pass-by-reference terms for Java. – Eser Aygün Feb 23 '12 at 12:46
0
import java.util.*;
public class Main
{
  int a,b;


void swap(Main ob)
{
    int tmp=ob.a;
    ob.a=ob.b;
    ob.b=tmp;
}

void get()
{
    Scanner sc=new Scanner(System.in);
    System.out.println("Enter a and b: ");
    a=sc.nextInt();
    b=sc.nextInt();
}

public static void main(String[] args) {
    Main ob=new Main();
    ob.get();
    ob.swap(ob);
    System.out.println(ob.a+" "+ob.b);
}}