Java 最终对象更改原始对象的值

Java 最终对象更改原始对象的值,java,android,arraylist,final,Java,Android,Arraylist,Final,我有一个POJO类Contact,其中包含地址簿中联系人的姓名、电子邮件和照片URI。活动开始时,我查询联系人并检索所有联系人,然后在ArrayList中分配它。此ArrayList用于显示RecyclerView列表中的所有联系人 当用户单击它时,我会打开一个弹出窗口,显示一个警告对话框,并在EditText中填写用户名和电子邮件。用户可以编辑详细信息并保存它。保存后,我将该联系人对象添加到所选联系人列表的另一个数组列表 当用户编辑一些联系信息并保存时,会出现问题。它还会更改所有联系人Arra

我有一个POJO类
Contact
,其中包含地址簿中联系人的姓名、电子邮件和照片URI。活动开始时,我查询联系人并检索所有联系人,然后在
ArrayList
中分配它。此
ArrayList
用于显示
RecyclerView
列表中的所有联系人

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

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

代码流:

存储数据的ArrayList:

ArrayList<Contact> mContacts = new ArrayList<>(); // This is filled with contact data
ArrayList<Contact> mSelectedContacts = new ArrayList<>(); // Initially empty
创建弹出窗口的方法:

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列表中。我可以看到,编辑的姓名也反映在所有联系人列表中(
mContacts
ArrayList)

我知道有一些难以理解的事情正在发生,但在哪里呢?提供硬参考的是
final
?或者使用
最终联系人ci调用
createNameEmailEditDialog()
导致损坏?还是别的什么


我如何防止它?

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

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

谢谢您的回答,您所说的防御性副本是什么意思?@kirtan403创建一个构造函数
联系人(联系人c)
并传递从那里的
列表中获得的
联系人。在这个构造函数中,只需从另一个
联系人
@kirtan403获取并设置值即可-检查复制构造函数是一种方法。。感谢@KevinEsche和Lastmind感谢您的回答,您所说的“防御副本”是什么意思?@kirtan403创建一个构造函数
联系人(联系人c)
,并传递从
列表中获得的
联系人。在这个构造函数中,只需从另一个
联系人
@kirtan403获取并设置值即可-检查复制构造函数是一种方法。。谢谢@KevinEsche和LastMind
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);
            }
        });
    }