1

Before I get in to details I'd like to make it clear that I do understand that Java is Pass-by-Value and not Pass-by-Reference, but I'm a little confused since I've seen some functions do that. I'd like to understand how are they doing it.

What I'd like to happen:

public void yo() {
    int a = 1;
    String b = "hello";
    Boolean c = false;

    doSomething(a,b,c);

    // a,b,c should have new values
}

public void doSomething(int x, String y, Boolean z) {
    // Do Something
}

Functions I've seen do this:

// Works in Android Development

int[] location = new int[2];
view.getLocationInWindow(location);

// `location` has a new value now
// Same happens when you run getLocationOnScreen(arg)

How does this work?

Community
  • 1
  • 1
Sheharyar
  • 73,588
  • 21
  • 168
  • 215
  • 1
    @Mike: OP references that question in the question, so I think a clearer answer is needed. – Keppil Jan 05 '15 at 08:10
  • 1
    `location` is an array and has the value of the memory address - you can change the contents of the array, yes, but not the memory address. – Smutje Jan 05 '15 at 08:11

5 Answers5

7

First off: You're absolutely correct, Java is purely pass-by-value.

The key thing to remember is that when we have a variable like location that refers to an array or object, the variable doesn't actually contain the array or object, it contains a reference to the array or object elsewhere in memory. This is the big difference between arrays/objects and primitives. Consider this code:

int primitive = 5;
int[] ref = new int[2];

That gives us this in memory:

+-----------+
| primitive |
+-----------+
| 5         |
+-----------+

+-----------+
| ref       |
+-----------+      +--------+
| reference |----->| int[2] |
+-----------+      +--------+
                   | 0      |
                   | 0      |
                   +--------+

Note the difference. So what is "reference" in the above? It's a value, like 123456789, that the VM uses to locate the array in memory. We can't know the value, and we don't care about it. All we care about is that the VM knows how to interpret it.

So the code you quoted can modify the array because the value passed into the function is a copy of the reference to the array, not a copy of the array. Using that reference to modify the array modifies that one copy of the array, and so you can see those modifications regardless of which copy of the reference you're using to look.

After this line:

int[] location = new int[2];

...we have this in memory:

+-----------+
| location  |
+-----------+       +--------+
| reference |------>| int[2] |
+-----------+       +--------+
                    | 0      |
                    | 0      |
                    +--------+

Then, when you do this:

view.getLocationInWindow(location);

within getLocationInWindow, it receives a copy of the reference (because Java is pass-by-value), so say getLocationInWindow's argument name is foo, during the call we have this:

+-----------+
| location  |
+-----------+       +--------+
| reference |---+-->| int[2] |
+-----------+   |   +--------+
                |   | 0      |
                |   | 0      |
+-----------+   |   +--------+
| foo       |   |
+-----------+   |
| reference |---+
+-----------+

Accessing the array, through either copy of the reference, accesses the same array. (And again, this is also true for object references.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

There is a fundamental difference between passing a value (i.e. a primitive type, e.g. int, double, etc), and passing a reference to an object. If you change a property of the object the reference is pointing to, you will update the original object. Objects are not passed by value. You pass a reference to the object.

This is why it works when you pass a reference to an array, and not when you pass an integer (i.e.)

Erik A. Brandstadmoen
  • 10,430
  • 2
  • 37
  • 55
2
public class Main {

    public void changeArrayContents(int[] array) {
         array[0]++;
    }

    public void makeArrayNull(int[] array) {
         array = null;
    }

    public static void main(String[] args) {
         int[] array = new int[5];
         array[0] = 3;
         System.out.println(array[0]); // prints 3 (duh)
         changeArrayContents(array);
         System.out.println(array[0]); // prints 4
         makeArrayNull(array);
         System.out.println(array[0]); // prints 4 (does not throw NullPointerException)
    }
}

In this example code, changeArrayContents does not change its argument. The only way to change the value of a variable is by assignment - including compound assignment (+=, *=, etc) and the shortened forms with ++ and --.

"But there is a ++ in there!" you say. Yes, but notice that it's array[0]++, not array++. The thing being changed is array[0], not array.

When you write array[0] (or object.something), then the JVM goes to find the actual array - which is not stored in the variable - and accesses the first element.

Calling changeArrayContents(array) makes a copy of the variable array (just as it would if array was an int, or a boolean) but it does not copy the actual array that it refers to. There are now two references to the same array, and we can change it through either one and see the changes through the other.

Calling makeArrayNull(array) also makes a copy of the variable array, and doesn't copy the array itself. The difference here is that array = null affects only the parameter array. The local variable in main (also called array) is not affected.

user253751
  • 57,427
  • 7
  • 48
  • 90
1
int[] location = new int[2];
view.getLocationInWindow(location);

// `location` has a new value now

I am not sure what do you mean 'value of location'. As variable 'location' is an array, it's value is a reference that point to the values of arrays. The value of the 'location' didn't changed, but the values of array changed.

location->location[1],location[2]

as above, changed is the value of location[1],location[2], not location.

Dongqing
  • 674
  • 1
  • 5
  • 19
1

When you pass an array to any method its reference is is passed to the method, that means if you change anything in the content of the array which was pointed by that referenced, it ll reflect the change when you return from the method. But in case if you point that reference to some other array, and return from the method, the existing array (or the content) will not be changed

shikjohari
  • 2,278
  • 11
  • 23