1

So say i put trigger.new in a list then i throw that list in a forloop and change field values. Well then somewhere at some point those values are saved to salesforce. In the context of before i don't have to do an update.

But what happens if i break up trigger.new into multiple lists based on some parameter. Say

list<object> newListOne = list<object>();
list<object> newListTwo = list<object>();

for(object r :trigger.new){
    if(field__c = 1){
        newListOne.add(r);
    } else if(field__c = 2){
        newListTwo.add(r);
    }
for(object n: newListOne){
    fieldTwo__c = 5;
}
for(object z: newListTwo){
    fieldTwo__c = 10;
}

Say i modify some field values in newListone fieldTwo__c = 5. Would that save in the before insert/update context without me having to do anything.

2 Answers 2

3

Yes, it would work just fine. It doesn't matter how many lists you split the data into.

Collection types (Maps, Sets, and Lists, but mostly just Maps and Lists in practice) store data for non-primitive types (that is, everything that isn't Integer, Boolean, String, etc...) as a reference as opposed to storing it as a value/copy.

So as long as you don't break the reference (e.g. by doing a .clone() of an SObject instance) when you put data into a collection, a change to a field in one location will be reflected across all references to the underlying SObject instance.

3
  • Primitives are stored on the heap as well, and can be referenced. See Object a = 1, b = 1; Assert.isTrue(a === b); versus Object a = 1, b = a; Assert.isTrue(a === b);. However, they're also immutable, so it doesn't matter in practice. 😅
    – sfdcfox
    Commented Feb 5 at 20:11
  • @sfdcfox I think that Object is the only primitive that is an exception (but I didn't work my way through all of the primitives the last time I tested that).
    – Derek F
    Commented Feb 5 at 20:17
  • You can't construct Objects, they're abstract. The Object / === compiler limitations are an illusion.
    – sfdcfox
    Commented Feb 5 at 20:35
2

In a computer, there is Random Access Memory (RAM). Each unit in RAM can store one byte (eight bits) of data. Each unit is uniquely addressed through its address. In object-oriented programming, such as Apex, there are two kinds of memory: stack and heap.

Stack memory stores function calls and statically allocated variables. Calling a method adds an entry to the stack called the stack frame. When a method returns, the stack removes that frame; if there are no more frames, the program knows it's done running.

Heap memory stores dynamically allocated memory, either from the new keyword or a library method, such as Trigger.new data. These values are tracked by the aforementioned "address", in Apex commonly called a "reference." When no more references to that address exist, the garbage collector (GC) can mark that memory as "free."

To conceptualize this better, try this code:

Account a = new Account(Name='Demo');
Account b = new Account(Name='Demo');
System.debug(a == b); // true
System.debug(a === b); // false

What this code is saying is that while the contents of the account records are the same, they are actually two different copies. Modifying a won't modify b.

So, Trigger.new has a reference that points to a List, and each element inside that list has references to each record, and each field inside each record has a literal value or a reference to a value on the heap.

So, even though there is no ID value in the field, the references provided identify each record uniquely, which is how the trigger knows which record to update, even if you assign the record to another variable or list. The references are copied, rather than the entire object.

It's worth noting that = is always a copy by reference operation. For example:

Object a = 1;
Object b = a;
System.debug(a == b); // true
System.debug(a === b); // true
b = 1;
System.debug(a == b); // true
System.debug(a === b); // false

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .