最终对象更改原始对象的值
final Object changes the value of original Object
我有一个 Contact
的 POJO class,其中包含地址簿中联系人的姓名、电子邮件和 photoUri。当 activity 开始时,我查询联系人并检索所有联系人并将其分配到 ArrayList<Contact>
中。而这个 ArrayList
用于显示 RecyclerView
列表中的所有联系人。
当用户点击它时,我会打开一个弹出窗口,其中显示一个警告对话框并填写用户名和电子邮件 EditText
。用户可以编辑详细信息并保存。保存后,我将 Contact
对象添加到所选联系人列表的另一个 ArrayList
中。
当用户编辑一些联系人信息并保存时出现问题。它还会更改所有联系人中的原始联系人详细信息 ArrayList
。
代码流程:
存储数据的数组列表:
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 列表中。我可以看到,编辑后的姓名也反映在所有联系人列表中 (mContacts
ArrayList)。
我知道有一些硬引用正在进行,但是在哪里?是 final
提供硬参考吗?或者用 final Contact ci
调用 createNameEmailEditDialog()
会造成损坏吗?或者其他什么?
我该如何预防?
您的引用 contact
是 final
,这意味着该引用不能指向任何其他内容。但是 contact
实例本身并不是 不可变的 。对于引用类型 final
不是 immutable
。尝试创建 contact
的防御副本并将其传递给您的方法(如果您不希望更改原始实例)。
我有一个 Contact
的 POJO class,其中包含地址簿中联系人的姓名、电子邮件和 photoUri。当 activity 开始时,我查询联系人并检索所有联系人并将其分配到 ArrayList<Contact>
中。而这个 ArrayList
用于显示 RecyclerView
列表中的所有联系人。
当用户点击它时,我会打开一个弹出窗口,其中显示一个警告对话框并填写用户名和电子邮件 EditText
。用户可以编辑详细信息并保存。保存后,我将 Contact
对象添加到所选联系人列表的另一个 ArrayList
中。
当用户编辑一些联系人信息并保存时出现问题。它还会更改所有联系人中的原始联系人详细信息 ArrayList
。
代码流程:
存储数据的数组列表:
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 列表中。我可以看到,编辑后的姓名也反映在所有联系人列表中 (mContacts
ArrayList)。
我知道有一些硬引用正在进行,但是在哪里?是 final
提供硬参考吗?或者用 final Contact ci
调用 createNameEmailEditDialog()
会造成损坏吗?或者其他什么?
我该如何预防?
您的引用 contact
是 final
,这意味着该引用不能指向任何其他内容。但是 contact
实例本身并不是 不可变的 。对于引用类型 final
不是 immutable
。尝试创建 contact
的防御副本并将其传递给您的方法(如果您不希望更改原始实例)。