5

Its probably a very simple one but its' still confusing me!

import java.util.ArrayList;

public class Sample {
    ArrayList<Integer> i = new ArrayList<>();
    ArrayList<Integer> j = new ArrayList<>();

    /**
     * @param args
     */
    public static void main(String[] args) {
        new Sample().go();
    }

    private void go() {

        i.add(1);
        i.add(2);
        i.add(3);

        j=i;

        i.remove(0);


        System.out.println(i + "asd" + j);
    }

}

I tried to print it :

[2, 3]asd[2, 3]

Why does j change when i changes? Does not happen with primitives though!

Mercenary
  • 2,106
  • 6
  • 34
  • 43
  • 1
    You should search for how Java deals with memory, specifically object references, and the difference between shallow/deep copying. – telkins Oct 24 '13 at 17:54

6 Answers6

10

The statement j=i; assigns the reference j to be the same reference as i. Now both i and j refer to the same ArrayList object. The removal of the 0th index is simply visible through both references.

If you would like the removal of an item in i not to affect the list from j, then create a copy of the list, instead of assigning the references:

j = new ArrayList<Integer>(i);

(It's a shallow copy, so the lists still refer to the same elements.)

rgettman
  • 176,041
  • 30
  • 275
  • 357
1

Use

j = new ArrayList<>(i);

or

Collections.copy(j, i);

to create a copy.

With j = i you only make j point on i (it's called reference). This applies to all assignments that involve objects (not primitive types like int or float)

micha
  • 47,774
  • 16
  • 73
  • 80
1

The Object is not cloned, just an additional object reference has been added. Since ArrayList is not immutable, any change to the object is reflected in both the object references.

A myth
  • 86
  • 1
  • 4
0

Objects and primitives work somewhat differently. Think of an object like i as being the name of that object. When you say j=i you're telling the JVM "forget about that other ArrayList that I said was called j; from now on when I refer to j, I mean this ArrayList that can also be called i. And indeed, that's exactly what happened: after that line, both variables refer to the same object.

Primitives work as you say. If you say i=5; j=i; i=6, then j will still be set to 5.

dcsohl
  • 7,186
  • 1
  • 26
  • 44
0

You created a memory stage for j with ; j = new ArrayList<>();
but then you said that let j refer to i's memory stage. So after j=i; any changes on i or j are going to effect both of them. Because they reference to the same objects.

Devrim
  • 15,345
  • 4
  • 66
  • 74
0

Let me do this in the following way for you:

ArrayList<Integer> i = new ArrayList<>();
ArrayList<Integer> j = new ArrayList<>();

// checking hash code before j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));

j = i;

// checking hash code after j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));

compare both the values if they are same that means after j=i; ArrayList j is now pointing to ArrayList i

In my machine o/p was:

30269696 //hashCode of i
24052850 //hashCode of j before j = i;

30269696 //hashCode of i and j are same after j = i that means they are pointing to same reference and hence change in one reflects on the other.
30269696
Vishrant
  • 15,456
  • 11
  • 71
  • 120