4

I created a list of contacts Inserted into database Create a new list and passed the previous list as a constructor parameter. Now when i make any changes in my new list,it gets reflected in my previous list as well.Why is it so.

I thought when you declare a new list with 'New' key word it got its own Heap area.and whatever changes happens,happens only in its own heap.and changes are local for it.

Code :

list<Contact> cts = new list<contact>();
for(integer x =0;x<5;x++){
    cts.add(new contact(lastname = 'cttest_'+string.valueof(x)));
}
insert cts;
map<contact,Integer> contactmap = new map<contact,integer>();

for (Integer x = 0; x<5;x++){
    contactmap.put(cts[x],x);
}
system.assertequals(contactmap.size(),5);
//system.debug('Limits:' + limits.getheapsize());
List<contact> samecontacts = new list<contact>(cts);
//system.debug('Limits:' + limits.getheapsize());
system.debug(samecontacts);

for(Integer x = 0; x<5;x++){
    samecontacts[x].assistantname = 'person'+string.valueof(x);
    system.assertequals(cts[x].assistantname,samecontacts[x].assistantname);
}
4

If you create a new list with an existing list as an argument only a shallow copy of the existing list is created. This means that the new list contains references to the same sObjects as the original list. To create a copy of an list, use the deepClone function. This will also create copies of the items in the list. See the List methods page for more help.

EDIT; with regard to the increase in heap size I've executed the following code:

list<Contact> cts = new list<contact>();
for(integer x =0;x<5;x++){
    cts.add(new contact(lastname = 'cttest_'+string.valueof(x)));
}

system.debug('Limits:' + limits.getheapsize());

List<contact> samecontacts = new list<contact>(cts);
system.debug('Limits:' + limits.getheapsize());

List<contact> samecontacts2 = cts.deepClone();
system.debug('Limits:' + limits.getheapsize());

Which yields the following USER_DEBUG lines:

14:23:22.034 (34880000)|USER_DEBUG|[6]|DEBUG|Limits:1218
14:23:22.035 (35020000)|USER_DEBUG|[9]|DEBUG|Limits:1242
14:23:22.035 (35213000)|USER_DEBUG|[12]|DEBUG|Limits:1386
9
  • But when you say new List<contact>(cts),i can see a heap size increase.why is it so? If new list has references,then only stack should be increased? – sfdc99999 Jul 1 '13 at 12:18
  • The increase of the heapsize is minimal (in the order of 30 bytes, in this case). Only the space needed for another list of references is added. If you make a copy of the list using deepClone you will see a much larger increase (about 150 bytes in this case). I updated my answer with some sample code and output. – rael_kid Jul 1 '13 at 12:22
  • Okay.so may be i am having some basic understanding issues :). My understanding was 1) wherever you specify with 'new operator' a separate heap space is created 2)references to a heap is stored in stack,not in heap.so when you say space needed for another list of reference,does that mean i got it wrong? – sfdc99999 Jul 1 '13 at 12:34
  • Well basically your Heap is the storage that is used for "global", persistent variables. The stack is used for variables that are only used in a shorter scope, for instance variables that you declare within a function. See this SO thread for further explaination: stackoverflow.com/questions/79923/… – rael_kid Jul 1 '13 at 12:41
  • Thanks for the link.But with respect to below,it does clearly say when its a variable with 'new operator' its different ----The copy of the memory address passed as a parameter is overwritten with the address of the newly allocated memory. The original, however, is not overwritten. That change in address is not known to the caller!---ref:blogs.developerforce.com/developer-relations/2012/05/… .This is my reference. – sfdc99999 Jul 1 '13 at 12:41
1

Below is the answer given by SFDCFOX user

List<Contact> cts = new List<Contact>();
 // let us say that List<Contact>() has memory address 1.

cts.add(new Contact(...)); // Contact has memory address 2; cts[0] points to 2.

List<Contact> samecontact = new List<Contact>(cts); // samecontact has memory address 3; it contains one element with reference to memory address 2.

As you can see, even though samecontact and cts point to different memory locations, no new Contact was created (2), so both indexes point to the same memory.

cts[0] = (reference:2) and samecontact[0] = (reference:2);

In contrast, if you use deepClone, you get the following:

List<Contact> cts = new List<Contact>(); // cts = reference:1 
cts.add(new Contact()); // cts[0] = reference:2 
List<Contact> ncts = cts.deepClone(true); // ncts = reference:3, ncts[0] = reference:4

Baseline is :- The references are copied, not the entire object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.