Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does creating an array from primitives copy them?

Tags:

java

arrays

In the program

public static void main(String[] args){
    int x = 1;
    int y = 2;
    int[] z = new int[]{x, y};
    z[0] = 3;
    System.out.println(x); //prints 1
}

I expected that 3 would be printed. But 1 was. Why? I thought Java makes copy only of references, i.e. when we pass a refrence to a method, the method will operate with another reference to the same object. It's like C++ pointers and primitive types.

So I tried to consult JLS 10.6 and didn't find anything useful about it. Maybe I've got some misunderstanding about primitive types in Java. Could you clarify?

like image 473
Alupkers Avatar asked Jan 06 '23 19:01

Alupkers


1 Answers

Why does creating an array from primitives copy them?

For exactly the same reason that:

int a = 5;
int b = a;

...copies the value of a into b, without creating any kind of link between a and b: The value is copied, not some kind of reference to the variable.


Re your comment:

But when we operate on reference types, the reference copies, doesn't it?

Yes, it does, exactly like the number gets copied in your int scenario.

b = a (or your array initializer) works exactly the same way regardless of whether a and b are primitive type variables or reference type variables: The value in a is copied to b, and then there is no ongoing link between a and b.

The only difference is that when you're dealing with reference types, the value in the variable isn't the actual thing, it's a reference to the actual thing. So copying that reference from one variable into another just makes makes those two variables refer to the same thing, just like my code above makes a and b both have the value 5.

Consider: Let's create a list:

List<String> a = new ArrayList<String>();

That gives us something like this in memory:

              +----------+
a(55465)----->| the list |
              +----------+

The variable a contains a value which is a reference to an object. I've depicted that value above as 55465, but we never actually see the raw value in our Java code (and it changes as garbage collection is done). It's just a value, like any other value, which tells the JVM where to find the object in memory. You can think of it like a long containing a memory address (that's not what it really is, but it works conceptually).

Now we do this:

List<String> b = a;

Now we have something like this in memory:


a(55465)--+
          |    +----------+
          +--->| the list |
          |    +----------+
b(55465)--+

Both a and b contain a value which refers to the list.

You can see how that's exactly like:

int a = 5

gives us

a(5)

and then

int b = a;

gives us

a(5)
b(5)

Values are copied between variables, passed into functions, etc. The only difference with reference types is what that value is used for, how it's interpreted.

If so, I would say that java is pass by value in the sense of copying values of primitives and the references of reference types. Right?

No. "Pass by value" and "pass by reference" have a specific meaning in computing: It's about having a reference to a variable, not an object. This is what pass-by-reference looks like:

// NOT JAVA; Java doesn't have this
void foo(int &a) { // Fake pass-by-reference thing
    a = 3;
}

int a = 5;
foo(&a); // Fake pass-by-reference operator
System.out.println(a); // 3

Pass-by-reference has nothing to do with object references. The only thing they have in common is the word "reference." Java is a purely pass-by-value language.

like image 138
T.J. Crowder Avatar answered Jan 19 '23 23:01

T.J. Crowder