【问题标题】:Variable Scope issues in java with custom objects arraylistjava中的变量范围问题与自定义对象arraylist
【发布时间】:2016-08-18 00:29:25
【问题描述】:

我有下一个代码: 一个 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 "beans" 的值。

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

我最近创建了一个克隆方法 getClone() 但是当我修改 ArrayList bean 时它仍然修改“克隆数组”

【问题讨论】:

  • 您的局部变量 beans 包含对与 AppVariables 相同的列表的引用。如果你想要一个副本,你必须明确地复制它。

标签: java android function scope


【解决方案1】:

我从不操纵他的值我只修改了本地变量beans的值

您看到该行为的原因是您的本地 var beans 引用了与 str 相同的 ArrayList&lt;Bean&gt; 对象。对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;
    }
}

【讨论】:

  • 我用 getClone() 方法更新了问题,但问题仍然存在
  • @DavidUntama 那是因为你没有进行深拷贝。
猜你喜欢
  • 1970-01-01
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多