1

I have the next code: a pojo class(Bean.java)

public class Bean {
    private int id;
    private String nom;

    public Bean(int id, String nom) {
        this.id = id;
        this.nom = nom;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }
}

and a app class that extends application this class is executed firsly (AppVariables.java)

public class AppVariables extends Application {
    private ArrayList<Bean> str;

    @Override
    public void onCreate() {
        super.onCreate();
        str = new ArrayList<>();
        str.add(new Bean(0, "java"));
        str.add(new Bean(0, "jelly"));
        str.add(new Bean(0, "hot"));
        str.add(new Bean(0, "weird"));


    }

    public ArrayList<Bean> getListStr() {
        return str;
    }

public ArrayList<Bean> getClone() {
        ArrayList<Bean> r = new ArrayList<>(2);
        r.add(str.get(2));
        r.add(str.get(3));
        return r;
    }
}

and my main activity that launches (MainActivity.java)

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AppVariables app = (AppVariables) getApplicationContext();

        ArrayList<Bean> beans = app.getListStr();

        beans.get(0).setNom("C++");


        String r = "";
        for (Bean b : beans) {
            r += b.getNom() +"\n";
        }
        Toast.makeText(this, r, Toast.LENGTH_LONG).show();

        ArrayList<Bean> clone = app.getClone();
        beans.get(3).setNom("HOT");
        r = "";
        for (Bean b : clone) {
            r += b.getNom() +"\n";
        }
        Toast.makeText(this, r, Toast.LENGTH_LONG).show();

    }
}

The question is: Why when I read the ArrayList str, it is modified? I never manipulate its values, I only modified the value of the local var "beans".

The two Toast show me the same string.

I recently create a clone method getClone() but when I modified the ArrayList bean it still modify the "cloned array"

Sufian
  • 6,405
  • 16
  • 66
  • 120
David Untama
  • 488
  • 3
  • 18
  • 5
    Your local variable `beans` holds a reference to the same list as `AppVariables` has. If you wanted a copy, you would have to copy it explicitly. – shmosel Aug 18 '16 at 00:32

1 Answers1

4

I never manipulate his values I only modified the value of the local var beans

The reason for the behavior that you see is that your local var beans references the same ArrayList<Bean> object as str. Any modifications to beans are done directly on the str.

The root cause of the problem is this implementation of the getter:

public ArrayList<Bean> getListStr() {
    return str;
}

You need to make and return a deep copy of the list to avoid this behavior. Simply copying the list will not do, because you alter the object inside the collection.

I update the question with a getClone() method but the issue still remains

That's because you did not make a deep copy. Here is how you can fix this:

// Add a copy constructor
public Bean(Bean other) {
    this.id = other.id;
    this.nom = other.nom;
}
// Make copies in getClone()
public ArrayList<Bean> getClone() {
        ArrayList<Bean> r = new ArrayList<>(2);
        r.add(new Bean(str.get(2)));
        r.add(new Bean(str.get(3)));
        return r;
    }
}
Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523