DRastislav
DRastislav

Reputation: 1882

Update of reference variable

i would like to ask, where is the difference between two examples:

class PassA 
{
    public static void main(String [] args) 
    {
        PassA p = new PassA();
        p.start();
    }

    void start() 
    {
        long [] a1 = {3,4,5};
        long [] a2 = fix(a1);
        System.out.print(a1[0] + a1[1] + a1[2] + " ");
        System.out.println(a2[0] + a2[1] + a2[2]);
    }

    long [] fix(long [] a3) 
    {
        a3[1] = 7;
        return a3;
    }
}

in code above:

  1. The reference variables a1 and a3 refer to the same long array object. When the [1] element is updated in the fix() method, it is updating the array referred to by a1. The reference variable a2 refers to the same array object. So Output: 3+7+5+" "3+7+5

but in code below

class Test 
{
    public static void main(String [] args) 
    {
        Test p = new Test();
        p.start();
    }

    void start() 
    {
        boolean b1 = false;
        boolean b2 = fix(b1);
        System.out.println(b1 + " " + b2);
    }

    boolean fix(boolean b3) 
    {
        b3 = true;
        return b3;
    }
}
  1. The boolean b1 in the fix() method is a different boolean than the b1 in the start() method. The b1 in the start() method is not updated by the fix() method.

Question

What is the difference?And how can I change code (example 1 ) so a1 won´t be changed?

Upvotes: 0

Views: 151

Answers (4)

Kostas Kryptos
Kostas Kryptos

Reputation: 4111

In Java everything is passed by value (see here).

Basically, there are three cases of variables passed to a function:

  1. primitive types(boolean, byte, short, int, long, float, double, char)
  2. Immutable Objects (such as String)
  3. Mutable Objects (note that native arrays, even of primitive types, are mutable, so the value is the reference to the array)

for the first two cases, the contents are not altered (e.g. your example 2 passing a boolean)

in the third case, the contents can be altered (e.g. your example 1 passing a long[]).

So, how not to alter your long[] in example 1? It is not possible with primitive arrays (except if you create another array inside the function using a for loop for copying all the items of the input to this new array and then make your operations to this copy). Or create a copy of the initial array before calling the function and invoke the function with this copy as input.

Apart from copying all the contents to another array, immutable native primitive arrays do not exist. You'll need to use a List or some other data structure:. You'll need to use a List or some other data structure (see here)

Upvotes: 1

Jobs
Jobs

Reputation: 3377

Java passes in by value, meaning only a copy of the original is passed into the method. However, here's the difference:

Refer to the below classical bad-swap example:

public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
 var2 = temp;
}

Here, it's a badSwap because var1 and var2 are left unchanged. Only copies of those integers are swapped within the function.

Now, when a copy is made of your 'al' array reference in your example, the copy of 'al' still refers to your original {3, 4, 5} array.

Thus, when you do the following:

long [] a1 = {3,4,5};
long [] a2 = fix(a1);

a3[1] = 7 in the fix(al) method changes the value of the original al.

Instead, pass in a copy of the array itself.

Points to remember:

A copy of a reference still refers to the same thing, whereas a copy of a primitive type (int, boolean..) is completely separate from the original.

Upvotes: 0

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280132

Drawings

a1 => Long object ID 9999: [3, 4, 5]
a3 => Long object ID 9999: [3, 4, 5] (ie. same object)

You then do

a3[1] = 7;

we dereference a3 and get

Long object ID 9999: [primitive long value: 3, primitive long value: 4, primitive long value: 5] 

we then access element at index 1 and change its value to 7

Long object ID 9999: [primitive long value: 3, primitive long value: 7, primitive long value: 5] 

In the second case

b1 = primitive boolean value: false
b3 = primitive boolean value: false (no relation to the other, just another false)

You then do

b3 = true;

this changes only b3

b3 = primitive boolean value: true (still no relation)

This is because Java is a pass-by-value language.

To change your first snippet, you'd have to make a copy of the array and pass that copy when invoking the method.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726909

In Java everything is passed by value, including object references. In both cases a copy of the parameter a3 or b3 is made. However, a copy of an object reference continues referring to the same object, while a copy of a primitive becomes completely disconnected from the original.

To make the first example behave like the second one, create a copy of your array (which is a reference-type object) prior to modifying it:

long [] fix(long [] a3) 
{
    long[] res = Arrays.copyOf(a3, a3.length);
    res[1] = 7;
    return res;
}

Upvotes: 1

Related Questions