-1
public class Test {
    public static void main(String[] args) {
        int[] arr = new int[5];
        arr[0]    = 1;
        method(arr);
        System.out.println(arr[0]);
    }

    private static void method(int[] array)
    {
        array[0] = 2;
    }
}

After invoking method, arr[0] becomes 2. Why is that!?

Voo
  • 29,040
  • 11
  • 82
  • 156
good_evening
  • 21,085
  • 65
  • 193
  • 298
  • 7
    You don't pass copies of the array around, you pass a value which is a reference to the array which allows you to modify the array from other functions. http://stackoverflow.com/questions/2831879/java-array-pass-by-reference-does-not-work – wkl Dec 12 '11 at 03:12
  • 2
    does this even compile? method(int[]) is called with a method(int) – aldrin Dec 12 '11 at 03:16
  • I wrote it directly without thinking, my mistake, sorry. – good_evening Dec 12 '11 at 03:35
  • Please start thinking before engaging typing fingers. – Andrew Thompson Dec 12 '11 at 04:11

7 Answers7

3

You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.

If Java were pass by reference, this would pass:

public class Test {

public static void main(String[] args) {
    Test test = new Test();
    int j = 0;
    test.setToOne(j);
    assert j == 1;
}

public void setToOne(int i) {
    i = 1;
}
}
Chip McCormick
  • 744
  • 4
  • 17
  • Nit: Pass-by-reference is different. Ref: http://en.wikipedia.org/wiki/Evaluation_strategy –  Dec 12 '11 at 03:16
  • What's worth mentioning that the value of an object variable is the reference to an object of the type. So while it really is call-by-value, in the case of non-primitives, the value is a reference. – G. Bach Dec 12 '11 at 03:25
  • @pst: Rewrote my answer a bit, hope it's clearer. I added the pass by reference info to answer the implied question: why can't Java replace a variable in a method but can mutate it's fields. – Chip McCormick Dec 12 '11 at 03:26
1

This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.

When you pass an object -- including arrays -- you pass the object itself. A copy is not created.

If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)

Here is the code above, annotated:

public static void main(String[] args)
{
    int[] arr = new int[5]; // create an array object. let's call it JIM.
    // arr evaluates to the object JIM, so sets JIM[0] = 1
    arr[0]    = 1;          
    System.out.println(arr[0]);  // 1
    method(arr);                 // fixed typo :-)
    // arr still evalutes to JIM
    // so this will print 2, as we "mutated" JIM in method called above
    System.out.println(arr[0]);  // 2
}

private static void method(int[] array)
{
    // array evaluates to the object JIM, so sets JIM[0] = 2
    // it is the same JIM object
    array[0] = 2;
}

Happy coding.


*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.

Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.


Additional:

  1. Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?

  2. Make copy of array Java -- note this only creates a "shallow" copy.

Community
  • 1
  • 1
  • That's, quite frankly, the silliest thing I've ever heard. Java is strictly call by value, just like C. A copy of the reference value is made and passed into the method being called. There's no reason to make up new terms for it ::sigh:: – Brian Roach Dec 12 '11 at 03:22
  • Quite frankly, I'm going to go with what James Gosling says, which is that Java is *only* call by value, rather than the wikipedia article. Of course, if you think wikipedia is a better source than the guy who *created* java ... hey, that's your call. – Brian Roach Dec 12 '11 at 03:25
  • Yes, I find fault with it. Java is *only* call by value. The Java Programming Language, 2nd ed. by Ken Arnold and James Gosling, section 2.6.1, page 40, 3rd paragraph. Pretty straight forward, the guys that wrote java disagree. – Brian Roach Dec 12 '11 at 03:30
  • @BrianRoach And gosling also once thought that `clone()` as a protected method in object was a good idea. But then in this case there's no contradiction whatsoever, so that's rather silly. The description here is accurate and describes the behavior of Java correctly so it's hardly "wrong". It also has the nice advantage of allowing one to explain the behavior without having to resort to low level things like references - which are themselves an abstraction for pointers (and you can't get much more low level than talking about memory addresses). – Voo Dec 12 '11 at 03:37
  • @BrianRoach I still prefer the term to describe these semantics, but I've updated the answer for "more conventional Java" thinking. Didn't mean to sound so hostile earlier. :) –  Dec 12 '11 at 03:54
1

Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm

aldrin
  • 4,482
  • 1
  • 33
  • 50
  • Yes, but pass-by-value for non-primitive types is easily understood pass-by-object-sharing. Otherwise we have to talk about "references" which really shouldn't *need* to be talked about in higher-level languages. –  Dec 12 '11 at 03:22
0

Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.

A quick example for thought:

If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.

ziesemer
  • 27,712
  • 8
  • 86
  • 94
0
method(arr[0]);

I think that's supposed to be

method(arr);

But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0

Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method

however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place

lynnyilu
  • 573
  • 1
  • 5
  • 15
0

Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.

BillRobertson42
  • 12,602
  • 4
  • 40
  • 57