11

Let me start by saying that I can't put any code here because Internet on my laptop is not working so I am posting this through my phone. Okay the problem is that say I have two classes: class one and two. Class one has an ArrayList as one of its attributes and it calls a void method from class two and passes that ArrayList as a parameter. Now that method initializes another ArrayList and makes it equal to the parameter passed by me and makes changes to that new ArrayList. Funny thing is that even my original ArrayList which was passed as parameter is also changing. What could be the possible reason?

Chris Dargis
  • 5,891
  • 4
  • 39
  • 63
Sahil Chaudhary
  • 493
  • 2
  • 10
  • 29
  • I guess because you have 2 references to the same object in the heap. So any modification on the first reference would be reflected to the other one. See http://stackoverflow.com/a/9404727/597657 for more details. – Eng.Fouad Nov 22 '12 at 00:21
  • Did the list change (elements removed/added/reordered), or the elements within the list (their properties)? – Andy Nov 22 '12 at 16:59

6 Answers6

6

The problem is that when you use = to make the new ArrayList a copy of the original, you're just creating a new reference to the same ArrayList. Think of it as two variables pointing at the same object.

Check this out, it might help you understand what's happening: Is Java "pass-by-reference" or "pass-by-value"?

In order to solve your problem, you need to create a new ArrayList by using the "new" keyword and then adding all of the objects, or use the clone() method.

Community
  • 1
  • 1
mauro.dec
  • 556
  • 1
  • 5
  • 9
3

The reason is that when you pass an ArrayList as argument, the called method can change the content of the array. The ArrayList contains references to Objects. If you want to avoid that some class will change the content of your ArrayList you have to give back Copy of your ArrayList where all objects inside are clone()s of the objects in your list.

Use object.clone()

ArrayList clonedCopy = new ArrayList(list1.size());
for (Object obj : list1) {
  clonedCopy.add(obj.clone());
}

Now give this clonedCopy back. But make sure obj is cloneable!

AlexWien
  • 28,470
  • 6
  • 53
  • 83
  • Correct point, but simpler code would be `ArrayList copy = new ArrayList(incomingList);` – user949300 Nov 22 '12 at 00:38
  • 3
    @user949300 NO! your code will not copy the objects inside the list, it will only copy a reference to it. If you would have a Date objects inside your list, and give yur copyied list to another class. that other class can change your Date object inside yourlist! Therefore clone, or use primitive types if possible (Date: better long) – AlexWien Nov 22 '12 at 00:43
  • True, and good point about using primitives / immutables. But, it depends if you want to allow the other class to make changes or not. Since OP mentioned that the method call was a void, it seems plausible that he wanted to allow changes. Otherwise it's not clear how the other method would actually do anything. – user949300 Nov 23 '12 at 19:57
3

Sample Code:

public class MethodArguments {

public static void main(String args[]) {

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

    a.add("Steve");

    a.add("Daniel");
    a.add("John");
    a.add("Maxi");
    a.add("Jeni");

    System.out.println(a);

    display(a);

    getSize(a);

}

static void display(ArrayList<String> arrayList1) {

    arrayList1.add("Pollard");

    System.out.println(arrayList1); // passing the arraylist values and
                                    // adding the element

}

static void getSize(ArrayList<String> arrayList1) {

    System.out.println(arrayList1.size()); // getting the size of arraylist
                                            // by passing arguments to
                                            // method
 }

}

Output:

[Steve, Daniel, John, Maxi, Jeni]

[Steve, Daniel, John, Maxi, Jeni, Pollard]

6

Stephen
  • 9,899
  • 16
  • 90
  • 137
1

Because they point to the same reference.

DarthVader
  • 52,984
  • 76
  • 209
  • 300
0

The = operator in Java will just copy the ArrayList reference (the same is for all objects). See this answer for making a deep copy of an ArrayList.

Community
  • 1
  • 1
Chris Dargis
  • 5,891
  • 4
  • 39
  • 63
0

This is because the new array list points to the same old array when you make it equal to.

This small example should clarify it.

import java.util.ArrayList;
import java.util.List;


public class JavaApplication1 {


    public static void main(String[] args) {

        List <String> origList = new ArrayList<>();
        origList.add("a");
        origList.add("b");

        JavaApplication1 app = new JavaApplication1();
        app.addToList(origList);

        for(String str:origList){            
            System.out.println(str);
        }

    }

    private void addToList(List<String> strList){
        System.out.println("inside addToList");
        List <String> newList = new ArrayList<>();
        // newList = strList; //This is how you are doing it
        newList.addAll(strList); //This is how you should do it.

        newList.add("x");
    }
}
PCM
  • 873
  • 8
  • 23
  • I guess you are missing the type annotation here `new ArrayList<>();` –  Nov 17 '18 at 02:20