带有自定义对象的Java中的变量范围问题arraylist

时间:2016-08-18 00:29:25

标签: java android function scope

我有下一个代码: pojo类(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;
    }
}

和扩展应用程序此类的应用程序类首先执行(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;
    }
}

和我启动的主要活动(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();

    }
}

问题是:为什么当我阅读ArrayList str时,它被修改了?我从不操纵它的值,我只修改了本地var&#34; bean&#34;的值。

两个Toast向我显示相同的字符串。

我最近创建了一个克隆方法getClone(),但是当我修改了ArrayList bean时,它仍然会修改&#34;克隆的数组&#34;

1 个答案:

答案 0 :(得分:4)

  

我从不操纵他的值我只修改了局部变量beans

的值

您看到的行为的原因是您的本地var beans引用与ArrayList<Bean>相同的str对象。对beans的任何修改都直接在str上完成。

问题的根本原因是getter的实现:

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

您需要制作并返回列表的deep copy以避免此行为。简单地复制列表是行不通的,因为你改变了集合中的对象。

  

我使用getClone()方法更新问题,但问题仍然存在

那是因为你没有制作一份很深的副本。以下是解决此问题的方法:

// 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;
    }
}