简体   繁体   中英

final Object changes the value of original Object

I have a POJO class of Contact which holds name, email and photoUri for a contact from address book. As the activity starts, I query contacts and retrieve all contacts and assign it in ArrayList<Contact> . And this ArrayList is used to show all contacts in RecyclerView list.

When a user clicks on it, I open a popup with showing a alert dialog and user's name and email filled in EditText . User can edit the details and save it. When it is saved I add that Contact Object in another ArrayList of selected contacts list.

The problem arises when user edits some contact information and save it. It also changes the original contacts details in the all contacts ArrayList .

Code flow:

ArrayLists where data is stored:

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

When User clicks on the contact, popup shows for editing contact details:

    @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
            }
        });

    }

Method that creates the 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);
            }
        });
    }

Now after the dialog dismiss, in the RecyclerView List. I can see that, edited name is also reflected in the all contacts list ( mContacts ArrayList).

I know there is something Hard reference is going on, but where? Is it final that provides hard reference? Or calling createNameEmailEditDialog() with a final Contact ci is causing the damage? Or anything else?

How can I prevent it?

Your reference contact is final which means the reference cannot point to anything else. But the contact instance itself is not immutable . For reference types final is NOT immutable . Try creating a defensive copy of contact and passing it to your method (if you don't want the original instance to be changed).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM