1

I want to remove word "a" from t1 object. Why t2 object also got affected?

Code:

package newproject;

import java.util.ArrayList;
import java.util.Arrays;

public class NewProject {

    public static void main(String[] args) {      
        String str[] = {"a", "b", "c"};
        ArrayList<String> words = new ArrayList<>();
        words.addAll(Arrays.asList(str));

        Test t1 = new Test(words);
        Test t2 = new Test(words);

        System.out.println("Result Before ");
        System.out.println("T1 " + t1.getWords());
        System.out.println("T2 " + t2.getWords());

        // Only T1 remove words, not T2
        t1.removeWords("a");

        System.out.println("Result After ");
        System.out.println("T1 " + t1.getWords());
        System.out.println("T2 " + t2.getWords());
    }   

}

class Test {
    private ArrayList<String> words;

    Test(ArrayList<String> words){
        setWords(words);
    }

    void setWords(ArrayList<String> words){
        this.words = words;
    }

    ArrayList <String> getWords() {
        return this.words;
    }

    void removeWords(String word) {
        this.words.remove(word);
    }
}
Gaurav Jeswani
  • 4,410
  • 6
  • 26
  • 47
asyraaf azhar
  • 383
  • 4
  • 12
  • 2
    *"Why t2 object also got affected."* Because `t1` and `t2` are sharing the same array list. – Stephen C Oct 14 '19 at 04:59
  • 1
    Let's assume you and your partner share a car and your partner uses all the gas in the tank. Is your car now empty as well? Of course, it's the same care. The same happens here, both `Test` instances work on the same ArrayList. – Tom Oct 14 '19 at 05:00
  • Is it because the ArrayList words is pass by reference, not by copy/value? I though each object will make a copy of ArrayList words – asyraaf azhar Oct 14 '19 at 05:16
  • 1
    [Is Java "pass-by-reference" or "pass-by-value"?](//stackoverflow.com/q/40480) – Tom Oct 14 '19 at 05:18

3 Answers3

0

Because both t1 and t2 share the same ArrayList. Instead of passing the ArrayList in to the constructor you want the constructor to say this.words = new ArrayList<String>(); to ensure that every instance of Test has it's own collection.

John3136
  • 28,809
  • 4
  • 51
  • 69
  • Thank you.How can I modify the code to make it work? I am still trying to understand. I try adding this.words = new ArrayList(); into the constructor, but the result is still the same – asyraaf azhar Oct 14 '19 at 05:10
  • Is it because the ArrayList words is pass by reference, not by copy/value? I though each object will make a copy of ArrayList words – asyraaf azhar Oct 14 '19 at 05:19
0

The issue is in setWords method. You can modify your setWords method to initialize a new Object of ArrayList rather than initializing your data member "words" to new Object in a constructor.

    void setWords(ArrayList<String> words){
        this.words = words;
    }

In the above snippet, your datamember this.words is assigned the reference of your parameter "words" (which was initialized in main) with new keyword. Both t1 and t2 will point to same reference. Instead change the method to

 void setWords(ArrayList<String> words){
            this.words = new ArrayList<>(words);
        }

This way a new ArrayList if created and assigned to your class object. Another way to overcome your problem if to do the following.

void setWords(ArrayList<String> words){
    this.words = new ArrayList();
    for(String s: words) {
        this.words.add(s);
    }
}

The point is everytime you create a class object, a new ArrayList must be created and assigned to your data member "words".

AnonymousFox
  • 118
  • 7
0

Simply because, both t1 and t2 access the same list. (The passing value is the same, which is words that you create and pass into constructors)

You may either pass two new Lists to the constructor.

Test t1 = new Test(new ArrayList(words));
Test t2 = new Test(new ArrayList(words));

Or You can create a new List inside the constructor

this.words = new ArrayList(words);

Supun Wijerathne
  • 11,964
  • 10
  • 61
  • 87