1

I understand that passing an array to a method is still Pass-By-Value, however the "value" that is passed is the reference of the array. This implies that changing the contents of the array would cause the contents to get updated in an earlier frame (if it's a recursive algorithm), or when it goes back to the main method, for that matter.

import java.util.Arrays;

public class SameArrayPassedOn{
    public static void main(String[] args) {
        int[] a = {1,1,1};

        print(a);
        fun(a,0);
        print(a);
    }

    static void fun(int[] b, int count)
    {
        if(count == 1)
            return;

        b[0] = b[1] = b[2] = 2; 
        fun(b,1);
    }

    static void print(int[] a)
    {
        for(int x : a)
            System.out.print(x + " ");
        System.out.println("");
    }
}

Output 111 222

However, if you create a new array, like for example, in the code below, since the reference is changed, the updates won't be reflected when you go back to the main method.

import java.util.Arrays;

public class NewArrayCreatedAndReferencePassedOn{
    public static void main(String[] args) {
        int[] a = {1,1,1};

        print(a);
        fun(a,0);
        print(a);
    }

    static void fun(int[] b, int count)
    {
        if(count == 1)
            return;

        int[] newb = {2,2,2};
        fun(newb,1);
    }

    static void print(int[] a)
    {
        for(int x : a)
            System.out.print(x + " ");
        System.out.println("");
    }
}

Output 111 111

However, my question is, why such a design was chosen for Arrays. Why couldn't it be that, just like for a primitive data type, say, integer variable, a new int is created every time it's passed inside a function, although we are not explicitly creating a new int, or declaring one. Like for example,

import java.util.Arrays;

public class SameIntPassedOn_ButNewCopyCreatedEachFrame {
    public static void main(String[] args) {
        int i = 0;

        fun(i);
    }

    static void fun(int b)
    {
        System.out.println(b);

        if(b == 10)
            return;

        b = b+1;
        fun(b);

        System.out.println(b);
    }
}

Output

0 1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1

Had the same been done for arrays, it would've allowed us to have a different copy of the array for each frame of the recursive function, which would've been very handy.

I think it would've been nice to have uniformity in behavior, because at the moment, it looks as though, to achieve the same behavior with Arrays, as is exhibited by primitive data types, such as int, float etc, when passed to a method, it is necessary to use a 'new' keyword, and create a new array before passing on to the method.

Community
  • 1
  • 1
saltandwater
  • 791
  • 2
  • 9
  • 25
  • 2
    @VinceEmigh Java is *always* pass by value. As OP states, correctly: "passing an array to a method is still Pass-By-Value, however the "value" that is passed is the reference of the array" – Andy Turner Jul 06 '16 at 20:47
  • 3
    *Had the same been done for arrays, it would've allowed us to have a different copy of the array for each frame of the recursive function, which would've been very handy.* Nothing is stopping you from copying the array, whereas with your approach, there would be no way to call a function **without** copying the array. – Elliott Frisch Jul 06 '16 at 20:47
  • This would require copying the entire array ( with the current impl of Java arrays). Efficient immutable arrays requires a tree based impl like in Scala's Vector – Sleiman Jneidi Jul 06 '16 at 20:53
  • 1
    Consider that copying an array "to be consistent with primitives" would make the behaviour inconsistent with all other reference types, which are not copied when they are passed as arguments to methods. – Andy Turner Jul 06 '16 at 20:56
  • @SleimanJneidi, thanks for the reply. By copying the array, do you mean, saving the state of the array in stack, before making the next function call? Would like some confirmation, please. – saltandwater Jul 06 '16 at 21:08
  • @AndyTurner, "would make the behaviour inconsistent with all other reference types, which are not copied when they are passed as arguments to methods". Thanks for the reply, but why are these reference types, not copied then? Is it because saving the state of the array and storing in stack at each function call, would consume space and time, rendering it inefficient? Whereas with primitive data types, you know the size can only be so much, so it doesn't affect performance much.? – saltandwater Jul 06 '16 at 21:12
  • 1
    @saltandwater there is no standard mechanism for copying a reference type. `Cloneable` exists, but it is near-pathologically impossible to use correctly, and many types don't implement it. But yes, it would be a substantial performance hit to copy everything, all the time. – Andy Turner Jul 07 '16 at 09:14
  • 1
    @saltandwater also, bear in mind that the mechanism for passing variables to methods is no different to the mechanism for declaring a new variable: `Frobnitz a = new Frobnitz(); Frobnitz b = a;`. Either you are proposing that such an initialization would copy `a`, or that the two behaviors should be different, meaning more inconsistency, not less. – Andy Turner Jul 07 '16 at 09:17

3 Answers3

3

However, my question is, why such a design was chosen for Arrays.

There are several main reasons.

The first is performance - it would lead to extremely poor performance if a new copy of the array had to be created every single time a method was called on it, especially for recursive calls.

Had the same been done for arrays, it would've allowed us to have a different copy of the array for each frame of the recursive function, which would've been very handy.

The second is that you already have the option of passing a copy of the array if you want to - you can create a copy manually and pass that. This way the programmer has the most control - they can choose to let method calls modify the array, or they can choose to pass a copy, allowing each method call its on version of the array to work with. If we forced the programmer to use a copy all the time, they would lose the option of letting method calls modify the array, which can be extremely useful in some situations. The current design gives the programmer the most options.

Why couldn't it be that, just like for a primitive data type...

The last reason is that an array is not a primitive data type - it is an object. The decision was most likely made to make arrays as consistent as possible with the way other objects in Java behave.

nhouser9
  • 6,730
  • 3
  • 21
  • 42
  • I think you should emphasize in some way the part about how, if it were as OP preferred, then everyone else would be forced to have array copies instead of references; they wouldn't have a choice. You sort of hint at it by saying "they can choose", but IMO it's the deal breaker. Still good answer and +1. – Loduwijk Jul 13 '16 at 22:37
  • @Aaron Yeah that was what I was trying to say with the second point "you already have the option..." but I will make an edit to clarify even further. – nhouser9 Jul 13 '16 at 22:39
0

The answer is that all objects, in fact all method arguments are passed by value. Your assessment "Had the same been done for arrays" is wrong because the same is done for arrays. Arrays, like all object references, are passed by value. The copy of a primitive value sent to a method is the same value the caller passed. The copy of an array pointer sent to a method is the same value the caller passed. The copy of any object pointer sent to a method is the same value the caller passed. It points to the same object, because the pointer is copied by value.

Why, you ask? Because it's simple, it's valid, and really has no downside.

Lew Bloch
  • 3,364
  • 1
  • 16
  • 10
-1

Array is a container (data structure) that hold a set of objects.

Those objects could be huge or small. and the array could contain many objects

imagine with each array reference we do full copy

the language will be extremely slow and inefficient

So the main reason for this is the efficiency

Hani
  • 1,354
  • 10
  • 20
  • It is possible to have efficient immutable arrays btw, are u aware of persistent arrays? – Sleiman Jneidi Jul 06 '16 at 20:55
  • I was under the impression that the question here was not talking about creating new individual elements references to same objects . what I understood is complete copy of the array values . so that when you modify the objects of the array you are modifying new objects not the same old ones.see this sentence in the question "this implies that changing the contents of the array would cause the contents to get updated in an earlier frame" (changing the contents would still affect the old array if the objects are immutable and we don't assign new objs) – Hani Jul 06 '16 at 21:09
  • @Hani, not so sure about the downvotes. I thought I was able to understand your answer. By "copying", did you mean, saving the state of the array in stack for each frame, before making the next function call.? Please confirm. – saltandwater Jul 06 '16 at 21:25
  • 1
    @saltandwater exactly and that include as well all the objects the array is referencing. So we save the array and all the objects it point to on each frame – Hani Jul 06 '16 at 23:42