Rory McGurty
Rory McGurty

Reputation: 89

Changes to one object inadvertently changes another object

I am trying to work with lists in java and I am getting the following bug in my code(see below). I create a new list object L1 and pass it into function f. Inside function f I create a copy of L1 and name it L2. I do an add operation on L2 and return from the function. After I return the value of L1 has changed. How can this be? From what I understand the scope of L1 does not extend to function f, so L1 cannot be changed in function f. And L2 is a copy of L1 and is its own object so any changes to it should not change L1 either. Can someone explain this to me?

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

public class HelloWorld{

     public static void main(String []args){
        List<String> L1 = new ArrayList<String>();
        L1.add("H");
        L1.add("I");
        System.out.println(L1);
        
        f(L1);
        
        System.out.println(L1);
     }
     
     public static void f(List<String> myList){
         List<String> L2 = new ArrayList<String>();
         L2 = myList;
         
         L2.add("!");
         return;
     }
}

Which prints out

[H, I]
[H, I, !]

Upvotes: 2

Views: 346

Answers (2)

Nathan Hughes
Nathan Hughes

Reputation: 96385

The list passed in isn’t a copy of a list, it is a reference, it points to the list.

You passed a reference to a list into a method, that reference still points to the original list L1. Then you assign it to L2, and now L2 points to the original list. So no, you’re not changing a second object inadvertently, it’s the same object.

You can pass a reference into a method and it still points to the same object that it points to outside that method.

This is normal for languages that pass references by value. C and JavaScript and Lisp all behave similarly to this.

Upvotes: 1

chriptus13
chriptus13

Reputation: 717

The problem is that you're creating a new List L2 and then overwriting the reference with L2 = myList you should add every String value from myList instead. Try this.

public static void f(List<String> myList) {
    List<String> L2 = new ArrayList<>();
    for(String str : myList) L2.add(str);
    L2.add("!");
}

Since List is an object it is passed as reference to method f therefore if you do L2 = myList you're just saying that L2 points to the same List as myList. Read more here.

Also you don't have to return explicitly in void methods.

Finally notice that your method f doesn't really do much since it only creates a local new List and you're not returning it.

Upvotes: 1

Related Questions