【问题标题】:final Object changes the value of original Objectfinal Object 改变原始 Object 的值
【发布时间】:2016-07-14 05:35:34
【问题描述】:

我有一个Contact 的 POJO 类,其中包含地址簿中联系人的姓名、电子邮件和 photoUri。随着活动的开始,我查询联系人并检索所有联系人并将其分配到ArrayList<Contact>。而这个ArrayList用于显示RecyclerView列表中的所有联系人。

当用户点击它时,我会打开一个弹出窗口,其中显示一个警告对话框,用户名和电子邮件填写为EditText。用户可以编辑详细信息并保存。保存后,我将 Contact 对象添加到所选联系人列表的另一个 ArrayList 中。

当用户编辑一些联系信息并保存时,就会出现问题。它还会更改所有联系人ArrayList中的原始联系人详细信息。

代码流程:

存储数据的ArrayLists:

ArrayList<Contact> mContacts = new ArrayList<>(); // This is filled with contact data
ArrayList<Contact> mSelectedContacts = new ArrayList<>(); // Initially empty

当用户点击联系人时,弹出编辑联系人详细信息:

    @Override
    public void onBindViewHolder(ContactViewHolder contactViewHolder, final int position) {

        // Get the contact details at given position
        final Contact ci = contactList.get(position);

        ...

        contactViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createNameEmailEditDialog(ci);    // Opens Popup
            }
        });

    }

创建弹窗的方法:

private void createNameEmailEditDialog(final Contact contact) {

        final AlertDialog.Builder alert = new AlertDialog.Builder(this);

        ...

        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                    contact.setName(String.valueOf(nameEditText.getText()));
                    contact.setEmail(String.valueOf(emailEditText.getText()));
                    mSelectedContacts.add(contact);
                    dialog.dismiss();
                    addViewToSeletedBar(contact);
            }
        });
    }

现在对话框关闭后,在 RecyclerView 列表中。我可以看到,编辑的名字也反映在所有联系人列表中(mContactsArrayList)。

我知道有一些硬引用正在发生,但是在哪里?是final 提供了硬参考吗?或者用final Contact ci 调用createNameEmailEditDialog() 会造成损坏?还是别的什么?

如何预防?

【问题讨论】:

    标签: java android arraylist final


    【解决方案1】:

    您的引用 contactfinal,这意味着引用不能指向其他任何内容。但是contact 实例本身并不是不可变。对于引用类型final 不是immutable。尝试创建 contact 的防御性副本并将其传递给您的方法(如果您不希望更改原始实例)。

    【讨论】:

    • 感谢您的回答,您所说的防御性副本是什么意思?
    • @kirtan403 创建一个构造函数Contact(Contact c) 并传递您从List 那里获得的Contact。在这个构造函数中,只需从另一个 Contact 获取和设置值。
    • 复制构造函数是要走的路。感谢@KevinEsche 和 TheLostMind
    猜你喜欢
    • 1970-01-01
    • 2018-06-27
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 2015-09-08
    相关资源
    最近更新 更多