0

OK so I understand that Java is pass by value (including for References, it passes the Object by the VALUE of the reference - i.e. the address).

If so then why does the swap(int[] array) method - passing an array of primitives - work?

public class TestArraySwap {

    public static void swap(int a, int b) {
        int temp =b;
        b=a;
        a=temp;
    }

    public static void swap(int[]a) {
        int temp = a[1];
        a[1]=a[0];
        a[0]=temp;
    }

    public static void main(String[] args) {
        //Test Primitive swap
        int a=1;
        int b=2;
        System.out.println("a="+a +" b="+b);
        swap(a,b);
        System.out.println("a="+a +" b="+b);

        //Test array swap
        int[] array = new int[2];
        array[0]=1;
        array[1]=2;
        System.out.println("a[0]="+array[0] +" a[1]="+array[1]);
        swap(array);
        System.out.println("a[0]="+array[0] +" a[1]="+array[1]);
    }
}

The output is

a=1 b=2
a=1 b=2
a[0]=1 a[1]=2
a[0]=2 a[1]=1

The second swap works - I would expect it not to but perhaps I am missing something?

kellyfj
  • 6,586
  • 12
  • 45
  • 66

5 Answers5

3

The main method has a reference to an array:

R1 ------> [1, 2]

Then it calls the swap() method. So a copy of the reference to the same array is created and used by the swap() method:

 R1 -----> [1, 2]
             ^
             |
 R2 ---------|

Then the swap() method changes the content of the array:

 R1 -----> [2, 1]
             ^
             |
 R2 ---------|

And it returns. R1 still references the same array, whose content has been changed.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 1
    I downvoted because the essence of the answer is that in Java arrays (even of primitives) are Objects. Once that was clear, the fact that it was an array of primitives (and primitives are passed by value) was irrelevant. – kellyfj Nov 12 '13 at 20:23
  • 5
    @kellyfj that's covered in the basics: [Java tutorial Array](http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html): *An array is a container **object***. This answer explains this, the fact you didn't know it before posting the question doesn't mean you should downvote this answer. – Luiggi Mendoza Nov 12 '13 at 20:26
  • 3
    If my answer doesn't make it clear that Java passes copies of references to arrays, then I really don't know how to make it clearer. It looks like you thought Java arrays were passed by value. My answer explains that it's not the case. References to the array are passed. – JB Nizet Nov 12 '13 at 20:29
0

The swap works because you pass the address (reference) of the array to the method. The method then operates on that array -- the same one the other method has a reference to.

I really don't like the statement, "Java is pass by value." I think it's really confusing.


 public void methodA(){
     int[] values = {1,2}; 
    // MethodA stack frame has a register that contains a 
    //   memory address (let's say it's 0x1F) that points to a contiguous section of 
    //   memory sized for an integerarray of size 2. 
     methodB(values); // Pass the **memory address** (aka REFERENCE) not the register address
     System.out.println(values[0]); // Prints "100"
 } 

 public void methodB(int[] ints){
     // MethodB stack frame now has a register with the memory address (0x1F)
     //    of 'ints' which is the same address that MethodA stack frame has.
     //    The same REFERENCE
     ints[0] = 100; // Alter the value in mem of 0x1F+0
     ints = new int[2]; // The local register overwrites the memory address of 
                        // the REFERENCE value that was there with 
                        // a new memory address -- say 0x5A
                        // since it's not storing it in the same register 
                        // as MethodA, MethodA will not reflect this.


 }
MadConan
  • 3,749
  • 1
  • 16
  • 27
  • 1
    But Java **IS** pass by value. – Luiggi Mendoza Nov 12 '13 at 20:14
  • 1
    I love being anal about this. _pass the address (reference)_ is wrong. It passes a copy of the value of the address. – Sotirios Delimanolis Nov 12 '13 at 20:16
  • Java **IS** pass by value for primitive types. Unless you consider passing an adress by value still a by value pass. Of course it's by value, but conceptually it's be reference. – Hugo Tunius Nov 12 '13 at 20:16
  • No it isn't. If it were, you could not do what he's accomplishing. Are you, or are you NOT passing the reference value?? That's not the value of the object (i.e. a deep clone.) I'm welcome to my opinion. This is a semantic argument. – MadConan Nov 12 '13 at 20:16
  • @HugoTunius is pass by value for object references as well. – Luiggi Mendoza Nov 12 '13 at 20:16
  • 3
    If you think is not pass by value, just modify the `swap` method to exchange the values of two object references instead, test it and get your answer. – Luiggi Mendoza Nov 12 '13 at 20:17
  • @Luiggi: Nope. The value of the object is not a reference. The value of the object is what it's comprised of. – MadConan Nov 12 '13 at 20:17
  • @Mad But the object isn't passed. The value of the reference is copied and that is passed. – Sotirios Delimanolis Nov 12 '13 at 20:18
  • Yes it is. If you still don't believe it, try following my suggestion on the last comment. – Luiggi Mendoza Nov 12 '13 at 20:18
  • @LuiggiMendoza It would still be a pass by reference. In your example only the local copies of the adress would be modified and thus they wouldn't swap. It's still pass by reference because pass by value would mean that the whole objects get's deep copied. – Hugo Tunius Nov 12 '13 at 20:18
  • @HugoTunius try it and see that it is not pass by reference :). – Luiggi Mendoza Nov 12 '13 at 20:19
  • @Luiggi: Are you saying my statement is wrong? "The swap works because you pass the address (reference) of the array to the method. The method then operates on that array -- the same one the other method has a reference to." ?? – MadConan Nov 12 '13 at 20:19
  • Yes, your statement is wrong. Read the most voted answer to have a better understanding about what happens behind the scenes. – Luiggi Mendoza Nov 12 '13 at 20:19
  • wow. All of my debuggers must be giving me the wrong information then when I can see the **reference** address between two scope. – MadConan Nov 12 '13 at 20:20
  • @LuiggiMendoza We are arguing over the definition of pass by reference and pass by value. All I am saying is that objects in java are not deep copied when passed, I know that you will have local reference variables for them in the function. – Hugo Tunius Nov 12 '13 at 20:20
  • No they're not, but you're not understanding the Java programming concepts. – Luiggi Mendoza Nov 12 '13 at 20:20
  • @HugoTunius still, **it is not** pass by reference. **Never**. – Luiggi Mendoza Nov 12 '13 at 20:21
  • 2
    If Java were pass by reference, then it would be possible to do `a = new int[] { a[1], a[0] }` inside the swap method. But it is not. – BalusC Nov 12 '13 at 20:22
  • 2
    @LuiggiMendoza It's not pass by reference in the C++ sense, but it is pass by reference in the sense that the objects don't get copied. As I said it's a futile argument because we agree and it's really only a matter of terminology – Hugo Tunius Nov 12 '13 at 20:22
  • @HugoTunius is pass by value. Period. No matter which language or idiom you use. – Luiggi Mendoza Nov 12 '13 at 20:22
  • 1
    MadConan clearly states that the address is passed, and uses reference as a synonym. Sure, the latter is not exactly correct, but this whole exchange is a bit unnecessary. – Zong Nov 12 '13 at 20:24
  • If it wasn't confusing, this whole exchange wouldn't be happening. – MadConan Nov 12 '13 at 20:25
  • The reference is not passed. A copy of the value of the reference is passed. That clears everything up. – Sotirios Delimanolis Nov 12 '13 at 20:26
  • True that it's really confusing because there are no references in Java and for me 'value' is something associated with stored in stack (i.e. `struct` in C), not an object placed in heap. – Andrey Chaschev Nov 12 '13 at 20:46
  • @AndreyChaschev: "There are no references in Java"? – Oliver Charlesworth Nov 12 '13 at 20:57
  • @OliCharlesworth I always thought that this statement comes from C/C++ language. And their references are not Java's references as they allow modifying primitives. Anyway, it's always been confusing for me, so correct me if I'm wrong. I can also create a question on this confusion... – Andrey Chaschev Nov 12 '13 at 21:02
0

After some more searching I found this answer Array seems to be getting passed by reference in Java, how is this possible?

and of course the Java spec itself

In the Java programming language, arrays are objects

Community
  • 1
  • 1
kellyfj
  • 6,586
  • 12
  • 45
  • 66
0

Everything in Java is passed by value (by copy).

swap(int[] a) works, because it passes (copies) only an address of the beginning of an array. Later it directly modifies memory under that address (a[0]) and the next one (a[1]).

swap(int a, int b) doesn't work, because it modifies copies of integers.

Adam Stelmaszczyk
  • 19,665
  • 4
  • 70
  • 110
0

References in Java are something pointing to an object in heap. Arrays in Java are always allocated in heap. So arrays in Java are like normal objects.

References to objects in Java are stored in stack like primitive variables (int, long), it's a memory address stored in variable. So when they say that objects are passed by value, the literal meaning is that you copy address value into method parameters.

And for me this has always been confusing because though I do understand the process, I can't recall how it's properly named as

  • there are no references in Java
  • I'm always stuck when I hear the word 'value' applied to an object
Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68