Pass By Reference VS Pass by ValuePassing Strings by value causes memory problemHow to pass the string value to Opportunity owner field from custom object's vf page?Can a collection be passed to a method by reference?Comparison fails when converting Opportunity from/to JSONMultiselection paramter for picklist datatype soqlfault string: No such parameter param defined for the operation, please check the WSDL for the serviceHow to retrive second created opportunity on accountHow to query more than 50000 records in start method of batch apex?How to pass in a List<String> to a parameter when calling a class method in Test Classunable to pass an object to another method in apex

How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?

Document starts having heaps of errors in the middle, but the code doesn't have any problems in it

US visa is under administrative processing, I need the passport back ASAP

Stop and Take a Breath!

Does holding a wand and speaking its command word count as V/S/M spell components?

Phrase for the opposite of "foolproof"

Unexpected email from Yorkshire Bank

With a Canadian student visa, can I spend a night at Vancouver before continuing to Toronto?

Why other Westeros houses don't use wildfire?

Don’t seats that recline flat defeat the purpose of having seatbelts?

How to verbalise code in Mathematica?

Realistic Necromancy?

Packing rectangles: Does rotation ever help?

What happened to Captain America in Endgame?

Apply MapThread to all but one variable

Will a top journal at least read my introduction?

Why was Germany not as successful as other Europeans in establishing overseas colonies?

Fizzy, soft, pop and still drinks

Does a semiconductor follow Ohm's law?

How did Captain America manage to do this?

Sci fi novel series with instant travel between planets through gates. A river runs through the gates

Meaning of Bloch representation

Why is it that the natural deduction method can't test for invalidity?

How can I place the product on a social media post better?



Pass By Reference VS Pass by Value


Passing Strings by value causes memory problemHow to pass the string value to Opportunity owner field from custom object's vf page?Can a collection be passed to a method by reference?Comparison fails when converting Opportunity from/to JSONMultiselection paramter for picklist datatype soqlfault string: No such parameter param defined for the operation, please check the WSDL for the serviceHow to retrive second created opportunity on accountHow to query more than 50000 records in start method of batch apex?How to pass in a List<String> to a parameter when calling a class method in Test Classunable to pass an object to another method in apex






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








1















Context Around this Code: I am making a schedulable class run each Sunday to track a couple of metrics important to the team.



Question: I am looking to consolidate DML operations and a big part of this is understanding pass by reference vs pass by value.



I want to pass the salesOps user object to the method SDREfficiencyLastWeek. I made the return type void, because I figured that I will be passing this by reference and I can make all the updates in the method without having to anything.



Why I am confused:



https://developer.salesforce.com/blogs/developer-relations/2012/05/passing-parameters-by-reference-and-by-value-in-apex.html
I read the above article and am thrown off by the following statement:



"Non-primitive data type arguments, such as sObjects, are also passed into methods by value. "



If the object is indeed passed by reference, then the query for the salesOps user in my code should be sufficient enough to edit all fields on that object without actually having to state each field in the query.



global class SDREfficientMetricsSchedulable implements Schedulable 

global void execute(SchedulableContext sc)

User salesOps = [SELECT ID FROM USER WHERE id = '0056A000002Z3p9QAC'];
List<String> queries = new List<String>();

String contactsWorked_lastWeek = 'select count(id) results from contact where LastActivityDate = last_week';
queries.add(contactsWorked_lastWeek);

String demosSet_lastWeek = 'select count(id) results from form__c where CreatedDate = last_week';
queries.add(demosSet_lastWeek);

String demosCompleted_lastWeek = 'select count(id) results from opportunity where (stagename = 'Unqualified Demo Completed' OR stagename = 'Qualified Demo Completed' ) and RecordTypeId = '0126A000000yudDQAQ' and CloseDate = last_week';
queries.add(demosCompleted_lastWeek);

String qualifiedDemos_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and isclosed = false and SDR_Owner__c != null and CreatedDate = last_week';
queries.add(qualifiedDemos_lastWeek);

String closedWon_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and iswon = true and SDR_Owner__c != null and CloseDate = last_week';
queries.add(qualifiedDemos_lastWeek);



SDREfficiencyLastWeek(queries, salesOps);

update salesOps;



public void SDREfficiencyLastWeek(List<String> queries, User salesOps )
















share|improve this question






















  • When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

    – Phil W
    5 hours ago











  • I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

    – Phil W
    5 hours ago

















1















Context Around this Code: I am making a schedulable class run each Sunday to track a couple of metrics important to the team.



Question: I am looking to consolidate DML operations and a big part of this is understanding pass by reference vs pass by value.



I want to pass the salesOps user object to the method SDREfficiencyLastWeek. I made the return type void, because I figured that I will be passing this by reference and I can make all the updates in the method without having to anything.



Why I am confused:



https://developer.salesforce.com/blogs/developer-relations/2012/05/passing-parameters-by-reference-and-by-value-in-apex.html
I read the above article and am thrown off by the following statement:



"Non-primitive data type arguments, such as sObjects, are also passed into methods by value. "



If the object is indeed passed by reference, then the query for the salesOps user in my code should be sufficient enough to edit all fields on that object without actually having to state each field in the query.



global class SDREfficientMetricsSchedulable implements Schedulable 

global void execute(SchedulableContext sc)

User salesOps = [SELECT ID FROM USER WHERE id = '0056A000002Z3p9QAC'];
List<String> queries = new List<String>();

String contactsWorked_lastWeek = 'select count(id) results from contact where LastActivityDate = last_week';
queries.add(contactsWorked_lastWeek);

String demosSet_lastWeek = 'select count(id) results from form__c where CreatedDate = last_week';
queries.add(demosSet_lastWeek);

String demosCompleted_lastWeek = 'select count(id) results from opportunity where (stagename = 'Unqualified Demo Completed' OR stagename = 'Qualified Demo Completed' ) and RecordTypeId = '0126A000000yudDQAQ' and CloseDate = last_week';
queries.add(demosCompleted_lastWeek);

String qualifiedDemos_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and isclosed = false and SDR_Owner__c != null and CreatedDate = last_week';
queries.add(qualifiedDemos_lastWeek);

String closedWon_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and iswon = true and SDR_Owner__c != null and CloseDate = last_week';
queries.add(qualifiedDemos_lastWeek);



SDREfficiencyLastWeek(queries, salesOps);

update salesOps;



public void SDREfficiencyLastWeek(List<String> queries, User salesOps )
















share|improve this question






















  • When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

    – Phil W
    5 hours ago











  • I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

    – Phil W
    5 hours ago













1












1








1








Context Around this Code: I am making a schedulable class run each Sunday to track a couple of metrics important to the team.



Question: I am looking to consolidate DML operations and a big part of this is understanding pass by reference vs pass by value.



I want to pass the salesOps user object to the method SDREfficiencyLastWeek. I made the return type void, because I figured that I will be passing this by reference and I can make all the updates in the method without having to anything.



Why I am confused:



https://developer.salesforce.com/blogs/developer-relations/2012/05/passing-parameters-by-reference-and-by-value-in-apex.html
I read the above article and am thrown off by the following statement:



"Non-primitive data type arguments, such as sObjects, are also passed into methods by value. "



If the object is indeed passed by reference, then the query for the salesOps user in my code should be sufficient enough to edit all fields on that object without actually having to state each field in the query.



global class SDREfficientMetricsSchedulable implements Schedulable 

global void execute(SchedulableContext sc)

User salesOps = [SELECT ID FROM USER WHERE id = '0056A000002Z3p9QAC'];
List<String> queries = new List<String>();

String contactsWorked_lastWeek = 'select count(id) results from contact where LastActivityDate = last_week';
queries.add(contactsWorked_lastWeek);

String demosSet_lastWeek = 'select count(id) results from form__c where CreatedDate = last_week';
queries.add(demosSet_lastWeek);

String demosCompleted_lastWeek = 'select count(id) results from opportunity where (stagename = 'Unqualified Demo Completed' OR stagename = 'Qualified Demo Completed' ) and RecordTypeId = '0126A000000yudDQAQ' and CloseDate = last_week';
queries.add(demosCompleted_lastWeek);

String qualifiedDemos_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and isclosed = false and SDR_Owner__c != null and CreatedDate = last_week';
queries.add(qualifiedDemos_lastWeek);

String closedWon_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and iswon = true and SDR_Owner__c != null and CloseDate = last_week';
queries.add(qualifiedDemos_lastWeek);



SDREfficiencyLastWeek(queries, salesOps);

update salesOps;



public void SDREfficiencyLastWeek(List<String> queries, User salesOps )
















share|improve this question














Context Around this Code: I am making a schedulable class run each Sunday to track a couple of metrics important to the team.



Question: I am looking to consolidate DML operations and a big part of this is understanding pass by reference vs pass by value.



I want to pass the salesOps user object to the method SDREfficiencyLastWeek. I made the return type void, because I figured that I will be passing this by reference and I can make all the updates in the method without having to anything.



Why I am confused:



https://developer.salesforce.com/blogs/developer-relations/2012/05/passing-parameters-by-reference-and-by-value-in-apex.html
I read the above article and am thrown off by the following statement:



"Non-primitive data type arguments, such as sObjects, are also passed into methods by value. "



If the object is indeed passed by reference, then the query for the salesOps user in my code should be sufficient enough to edit all fields on that object without actually having to state each field in the query.



global class SDREfficientMetricsSchedulable implements Schedulable 

global void execute(SchedulableContext sc)

User salesOps = [SELECT ID FROM USER WHERE id = '0056A000002Z3p9QAC'];
List<String> queries = new List<String>();

String contactsWorked_lastWeek = 'select count(id) results from contact where LastActivityDate = last_week';
queries.add(contactsWorked_lastWeek);

String demosSet_lastWeek = 'select count(id) results from form__c where CreatedDate = last_week';
queries.add(demosSet_lastWeek);

String demosCompleted_lastWeek = 'select count(id) results from opportunity where (stagename = 'Unqualified Demo Completed' OR stagename = 'Qualified Demo Completed' ) and RecordTypeId = '0126A000000yudDQAQ' and CloseDate = last_week';
queries.add(demosCompleted_lastWeek);

String qualifiedDemos_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and isclosed = false and SDR_Owner__c != null and CreatedDate = last_week';
queries.add(qualifiedDemos_lastWeek);

String closedWon_lastWeek = 'select count(id) results from opportunity where RecordTypeId = '0126A0000004Ao6QAE' and iswon = true and SDR_Owner__c != null and CloseDate = last_week';
queries.add(qualifiedDemos_lastWeek);



SDREfficiencyLastWeek(queries, salesOps);

update salesOps;



public void SDREfficiencyLastWeek(List<String> queries, User salesOps )













apex






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 6 hours ago









Matthew MetrosMatthew Metros

684




684












  • When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

    – Phil W
    5 hours ago











  • I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

    – Phil W
    5 hours ago

















  • When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

    – Phil W
    5 hours ago











  • I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

    – Phil W
    5 hours ago
















When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

– Phil W
5 hours ago





When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually state in the query. All other fields are unset (and an attempt to directly read them will fail with an exception). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.

– Phil W
5 hours ago













I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

– Phil W
5 hours ago





I am assuming the code you have shown is purely for illustration. If this is your production code I recommend you consider avoiding explicit ID references as these do not port between orgs.

– Phil W
5 hours ago










2 Answers
2






active

oldest

votes


















4














There's two different meanings of "reference," which is probably the source of confusion even with veteran developers, especially in regards to Apex. Some developers consider passing a variable's memory in to a parameter as "by reference", and literal values as "by value". We see this frequently in languages like C:



#include <stdio.h>

void multiplyByTwoRef(int *source)

// We're modifying the caller's value!
*source = *source * 2;

int multiplyByTwo(int source)
// We're modifying a local copy here.
source = source * 2;
return source;


int main()


int myVar = 5;
multiplyByTwoRef(&myVar); // Here, & means "pass memory address"; this is a reference
printf("%i", myVar);
printf("%i", multiplyByTwo(myVar)); // Here, we output 20 (10 * 2)
printf("%i", myVar); // But we output 10 here again, myVar was not modified
return 0;



In Apex, of course, this doesn't happen; we can't access memory pointers directly, so people tend to call Apex pass-by-value. However, that is simply not true in the most literal sense.



Consider the following code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = x1, x3 = x1, x4 = x1;
System.debug(Limits.getHeapSize());


If you check the debug logs, you'll notice that only 8 bytes were allocated. It's also worth noting that an Integer is 8 bytes. However, we allocated x1, x2, x3, and x4, so we should have 32 bytes of heap usage, right? As it happens, this isn't true; x2, x3, and x4 all have a reference to x1.



You can see the difference if we change the code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = 5, x3 = 5, x4 = 5;
System.debug(Limits.getHeapSize());


Now, we've allocated four Integer objects in memory, although they all have the same value, they are not literally the same object.



In Apex, all variables point to an area in heap (or are null). Variables themselves are references. All the time. Apex hides this fact from developers by appearing to have pass-by-value for primitives and pass-by-reference for objects, but that's all it is, an illusion.



The only way one could consider Apex to be pass-by-value is to say that Apex always passes the memory addresses (values) of objects on the heap.



So, to answer your question, yes, if you pass in an sObject record to a method, you're passing a reference to the object on the heap. Any changes you make to the object will affect the caller's version of the object. Passing in a List, or a Map, or a custom class instance, will all affect the original object on the heap.



Note that you can't modify the parameter itself, as that would lose the reference on the heap. It won't affect the original caller's version, because you're creating a new object in memory. To compare:



public static void setFirstName(Contact record, String name) 
// This WILL affect the caller's object
record.FirstName = name;
record = new Contact();
// This won't affect the caller's object
record.FirstName = name.repeat(2);

// ...
Contact record = new Contact();
setFirstName(record, 'Sally');


The important thing to remember is that primitives are immutable, and cannot be directly modified. You may as well consider these pass-by-value, even though we're really passing references. Everything else is pass-by-reference, since modifying the object in the parameter will affect the original.






share|improve this answer























  • Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

    – Phil W
    3 hours ago


















2














When Apex code calls synchronous Apex code the non-primitive objects are passed by reference - a change to the content of a list, map, set, SObject or custom Apex object is reflected in the caller's context too.



I suggest that the "pass by value" statement in the article is referring to cases such as scheduled apex, batches etc. (asynchronous execution) where the state of the object is serialized to the database, and deserialized back into an object when that code is about to be executed. In this sense the original state of the object (such as a batch) is not impacted by the later, asynchronous execution of the processing in that object.



When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually request in the query. All other fields are unset (and an attempt to directly read them will fail with an exception - you can avoid this error by getting the populated fields map and interrogating this map instead). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.






share|improve this answer

























  • That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

    – sfdcfox
    4 hours ago











  • I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

    – Phil W
    3 hours ago











Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "459"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f260299%2fpass-by-reference-vs-pass-by-value%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














There's two different meanings of "reference," which is probably the source of confusion even with veteran developers, especially in regards to Apex. Some developers consider passing a variable's memory in to a parameter as "by reference", and literal values as "by value". We see this frequently in languages like C:



#include <stdio.h>

void multiplyByTwoRef(int *source)

// We're modifying the caller's value!
*source = *source * 2;

int multiplyByTwo(int source)
// We're modifying a local copy here.
source = source * 2;
return source;


int main()


int myVar = 5;
multiplyByTwoRef(&myVar); // Here, & means "pass memory address"; this is a reference
printf("%i", myVar);
printf("%i", multiplyByTwo(myVar)); // Here, we output 20 (10 * 2)
printf("%i", myVar); // But we output 10 here again, myVar was not modified
return 0;



In Apex, of course, this doesn't happen; we can't access memory pointers directly, so people tend to call Apex pass-by-value. However, that is simply not true in the most literal sense.



Consider the following code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = x1, x3 = x1, x4 = x1;
System.debug(Limits.getHeapSize());


If you check the debug logs, you'll notice that only 8 bytes were allocated. It's also worth noting that an Integer is 8 bytes. However, we allocated x1, x2, x3, and x4, so we should have 32 bytes of heap usage, right? As it happens, this isn't true; x2, x3, and x4 all have a reference to x1.



You can see the difference if we change the code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = 5, x3 = 5, x4 = 5;
System.debug(Limits.getHeapSize());


Now, we've allocated four Integer objects in memory, although they all have the same value, they are not literally the same object.



In Apex, all variables point to an area in heap (or are null). Variables themselves are references. All the time. Apex hides this fact from developers by appearing to have pass-by-value for primitives and pass-by-reference for objects, but that's all it is, an illusion.



The only way one could consider Apex to be pass-by-value is to say that Apex always passes the memory addresses (values) of objects on the heap.



So, to answer your question, yes, if you pass in an sObject record to a method, you're passing a reference to the object on the heap. Any changes you make to the object will affect the caller's version of the object. Passing in a List, or a Map, or a custom class instance, will all affect the original object on the heap.



Note that you can't modify the parameter itself, as that would lose the reference on the heap. It won't affect the original caller's version, because you're creating a new object in memory. To compare:



public static void setFirstName(Contact record, String name) 
// This WILL affect the caller's object
record.FirstName = name;
record = new Contact();
// This won't affect the caller's object
record.FirstName = name.repeat(2);

// ...
Contact record = new Contact();
setFirstName(record, 'Sally');


The important thing to remember is that primitives are immutable, and cannot be directly modified. You may as well consider these pass-by-value, even though we're really passing references. Everything else is pass-by-reference, since modifying the object in the parameter will affect the original.






share|improve this answer























  • Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

    – Phil W
    3 hours ago















4














There's two different meanings of "reference," which is probably the source of confusion even with veteran developers, especially in regards to Apex. Some developers consider passing a variable's memory in to a parameter as "by reference", and literal values as "by value". We see this frequently in languages like C:



#include <stdio.h>

void multiplyByTwoRef(int *source)

// We're modifying the caller's value!
*source = *source * 2;

int multiplyByTwo(int source)
// We're modifying a local copy here.
source = source * 2;
return source;


int main()


int myVar = 5;
multiplyByTwoRef(&myVar); // Here, & means "pass memory address"; this is a reference
printf("%i", myVar);
printf("%i", multiplyByTwo(myVar)); // Here, we output 20 (10 * 2)
printf("%i", myVar); // But we output 10 here again, myVar was not modified
return 0;



In Apex, of course, this doesn't happen; we can't access memory pointers directly, so people tend to call Apex pass-by-value. However, that is simply not true in the most literal sense.



Consider the following code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = x1, x3 = x1, x4 = x1;
System.debug(Limits.getHeapSize());


If you check the debug logs, you'll notice that only 8 bytes were allocated. It's also worth noting that an Integer is 8 bytes. However, we allocated x1, x2, x3, and x4, so we should have 32 bytes of heap usage, right? As it happens, this isn't true; x2, x3, and x4 all have a reference to x1.



You can see the difference if we change the code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = 5, x3 = 5, x4 = 5;
System.debug(Limits.getHeapSize());


Now, we've allocated four Integer objects in memory, although they all have the same value, they are not literally the same object.



In Apex, all variables point to an area in heap (or are null). Variables themselves are references. All the time. Apex hides this fact from developers by appearing to have pass-by-value for primitives and pass-by-reference for objects, but that's all it is, an illusion.



The only way one could consider Apex to be pass-by-value is to say that Apex always passes the memory addresses (values) of objects on the heap.



So, to answer your question, yes, if you pass in an sObject record to a method, you're passing a reference to the object on the heap. Any changes you make to the object will affect the caller's version of the object. Passing in a List, or a Map, or a custom class instance, will all affect the original object on the heap.



Note that you can't modify the parameter itself, as that would lose the reference on the heap. It won't affect the original caller's version, because you're creating a new object in memory. To compare:



public static void setFirstName(Contact record, String name) 
// This WILL affect the caller's object
record.FirstName = name;
record = new Contact();
// This won't affect the caller's object
record.FirstName = name.repeat(2);

// ...
Contact record = new Contact();
setFirstName(record, 'Sally');


The important thing to remember is that primitives are immutable, and cannot be directly modified. You may as well consider these pass-by-value, even though we're really passing references. Everything else is pass-by-reference, since modifying the object in the parameter will affect the original.






share|improve this answer























  • Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

    – Phil W
    3 hours ago













4












4








4







There's two different meanings of "reference," which is probably the source of confusion even with veteran developers, especially in regards to Apex. Some developers consider passing a variable's memory in to a parameter as "by reference", and literal values as "by value". We see this frequently in languages like C:



#include <stdio.h>

void multiplyByTwoRef(int *source)

// We're modifying the caller's value!
*source = *source * 2;

int multiplyByTwo(int source)
// We're modifying a local copy here.
source = source * 2;
return source;


int main()


int myVar = 5;
multiplyByTwoRef(&myVar); // Here, & means "pass memory address"; this is a reference
printf("%i", myVar);
printf("%i", multiplyByTwo(myVar)); // Here, we output 20 (10 * 2)
printf("%i", myVar); // But we output 10 here again, myVar was not modified
return 0;



In Apex, of course, this doesn't happen; we can't access memory pointers directly, so people tend to call Apex pass-by-value. However, that is simply not true in the most literal sense.



Consider the following code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = x1, x3 = x1, x4 = x1;
System.debug(Limits.getHeapSize());


If you check the debug logs, you'll notice that only 8 bytes were allocated. It's also worth noting that an Integer is 8 bytes. However, we allocated x1, x2, x3, and x4, so we should have 32 bytes of heap usage, right? As it happens, this isn't true; x2, x3, and x4 all have a reference to x1.



You can see the difference if we change the code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = 5, x3 = 5, x4 = 5;
System.debug(Limits.getHeapSize());


Now, we've allocated four Integer objects in memory, although they all have the same value, they are not literally the same object.



In Apex, all variables point to an area in heap (or are null). Variables themselves are references. All the time. Apex hides this fact from developers by appearing to have pass-by-value for primitives and pass-by-reference for objects, but that's all it is, an illusion.



The only way one could consider Apex to be pass-by-value is to say that Apex always passes the memory addresses (values) of objects on the heap.



So, to answer your question, yes, if you pass in an sObject record to a method, you're passing a reference to the object on the heap. Any changes you make to the object will affect the caller's version of the object. Passing in a List, or a Map, or a custom class instance, will all affect the original object on the heap.



Note that you can't modify the parameter itself, as that would lose the reference on the heap. It won't affect the original caller's version, because you're creating a new object in memory. To compare:



public static void setFirstName(Contact record, String name) 
// This WILL affect the caller's object
record.FirstName = name;
record = new Contact();
// This won't affect the caller's object
record.FirstName = name.repeat(2);

// ...
Contact record = new Contact();
setFirstName(record, 'Sally');


The important thing to remember is that primitives are immutable, and cannot be directly modified. You may as well consider these pass-by-value, even though we're really passing references. Everything else is pass-by-reference, since modifying the object in the parameter will affect the original.






share|improve this answer













There's two different meanings of "reference," which is probably the source of confusion even with veteran developers, especially in regards to Apex. Some developers consider passing a variable's memory in to a parameter as "by reference", and literal values as "by value". We see this frequently in languages like C:



#include <stdio.h>

void multiplyByTwoRef(int *source)

// We're modifying the caller's value!
*source = *source * 2;

int multiplyByTwo(int source)
// We're modifying a local copy here.
source = source * 2;
return source;


int main()


int myVar = 5;
multiplyByTwoRef(&myVar); // Here, & means "pass memory address"; this is a reference
printf("%i", myVar);
printf("%i", multiplyByTwo(myVar)); // Here, we output 20 (10 * 2)
printf("%i", myVar); // But we output 10 here again, myVar was not modified
return 0;



In Apex, of course, this doesn't happen; we can't access memory pointers directly, so people tend to call Apex pass-by-value. However, that is simply not true in the most literal sense.



Consider the following code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = x1, x3 = x1, x4 = x1;
System.debug(Limits.getHeapSize());


If you check the debug logs, you'll notice that only 8 bytes were allocated. It's also worth noting that an Integer is 8 bytes. However, we allocated x1, x2, x3, and x4, so we should have 32 bytes of heap usage, right? As it happens, this isn't true; x2, x3, and x4 all have a reference to x1.



You can see the difference if we change the code:



System.debug(Limits.getHeapSize());
Integer x1 = 5, x2 = 5, x3 = 5, x4 = 5;
System.debug(Limits.getHeapSize());


Now, we've allocated four Integer objects in memory, although they all have the same value, they are not literally the same object.



In Apex, all variables point to an area in heap (or are null). Variables themselves are references. All the time. Apex hides this fact from developers by appearing to have pass-by-value for primitives and pass-by-reference for objects, but that's all it is, an illusion.



The only way one could consider Apex to be pass-by-value is to say that Apex always passes the memory addresses (values) of objects on the heap.



So, to answer your question, yes, if you pass in an sObject record to a method, you're passing a reference to the object on the heap. Any changes you make to the object will affect the caller's version of the object. Passing in a List, or a Map, or a custom class instance, will all affect the original object on the heap.



Note that you can't modify the parameter itself, as that would lose the reference on the heap. It won't affect the original caller's version, because you're creating a new object in memory. To compare:



public static void setFirstName(Contact record, String name) 
// This WILL affect the caller's object
record.FirstName = name;
record = new Contact();
// This won't affect the caller's object
record.FirstName = name.repeat(2);

// ...
Contact record = new Contact();
setFirstName(record, 'Sally');


The important thing to remember is that primitives are immutable, and cannot be directly modified. You may as well consider these pass-by-value, even though we're really passing references. Everything else is pass-by-reference, since modifying the object in the parameter will affect the original.







share|improve this answer












share|improve this answer



share|improve this answer










answered 4 hours ago









sfdcfoxsfdcfox

267k13213461




267k13213461












  • Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

    – Phil W
    3 hours ago

















  • Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

    – Phil W
    3 hours ago
















Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

– Phil W
3 hours ago





Now I don't know for sure, but I strongly suspect Apex does not actually pass primitive parameters in method calls as pointers but rather, as Java would, as actual values. The values are pushed on the stack. Primitives are, at their largest, double values (8 bytes). This excludes String. I would say these should be viewed as non-primitives that are actually simply immutable. The notion of Integer, Decimal etc. is almost certainly the same concept of box types, with auto boxing and unboxing around parameter passing. I accept I could be wrong since I have no access to the Apex runtime code.

– Phil W
3 hours ago













2














When Apex code calls synchronous Apex code the non-primitive objects are passed by reference - a change to the content of a list, map, set, SObject or custom Apex object is reflected in the caller's context too.



I suggest that the "pass by value" statement in the article is referring to cases such as scheduled apex, batches etc. (asynchronous execution) where the state of the object is serialized to the database, and deserialized back into an object when that code is about to be executed. In this sense the original state of the object (such as a batch) is not impacted by the later, asynchronous execution of the processing in that object.



When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually request in the query. All other fields are unset (and an attempt to directly read them will fail with an exception - you can avoid this error by getting the populated fields map and interrogating this map instead). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.






share|improve this answer

























  • That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

    – sfdcfox
    4 hours ago











  • I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

    – Phil W
    3 hours ago















2














When Apex code calls synchronous Apex code the non-primitive objects are passed by reference - a change to the content of a list, map, set, SObject or custom Apex object is reflected in the caller's context too.



I suggest that the "pass by value" statement in the article is referring to cases such as scheduled apex, batches etc. (asynchronous execution) where the state of the object is serialized to the database, and deserialized back into an object when that code is about to be executed. In this sense the original state of the object (such as a batch) is not impacted by the later, asynchronous execution of the processing in that object.



When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually request in the query. All other fields are unset (and an attempt to directly read them will fail with an exception - you can avoid this error by getting the populated fields map and interrogating this map instead). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.






share|improve this answer

























  • That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

    – sfdcfox
    4 hours ago











  • I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

    – Phil W
    3 hours ago













2












2








2







When Apex code calls synchronous Apex code the non-primitive objects are passed by reference - a change to the content of a list, map, set, SObject or custom Apex object is reflected in the caller's context too.



I suggest that the "pass by value" statement in the article is referring to cases such as scheduled apex, batches etc. (asynchronous execution) where the state of the object is serialized to the database, and deserialized back into an object when that code is about to be executed. In this sense the original state of the object (such as a batch) is not impacted by the later, asynchronous execution of the processing in that object.



When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually request in the query. All other fields are unset (and an attempt to directly read them will fail with an exception - you can avoid this error by getting the populated fields map and interrogating this map instead). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.






share|improve this answer















When Apex code calls synchronous Apex code the non-primitive objects are passed by reference - a change to the content of a list, map, set, SObject or custom Apex object is reflected in the caller's context too.



I suggest that the "pass by value" statement in the article is referring to cases such as scheduled apex, batches etc. (asynchronous execution) where the state of the object is serialized to the database, and deserialized back into an object when that code is about to be executed. In this sense the original state of the object (such as a batch) is not impacted by the later, asynchronous execution of the processing in that object.



When you query an object from the DB into an SObject in Apex, the SObject in Apex is only populated with the fields you actually request in the query. All other fields are unset (and an attempt to directly read them will fail with an exception - you can avoid this error by getting the populated fields map and interrogating this map instead). Note, however, that you can set any fields you like in that SObject, whether or not you queried them, and update the object in the DB using that modified state.







share|improve this answer














share|improve this answer



share|improve this answer








edited 5 hours ago

























answered 5 hours ago









Phil WPhil W

1,113311




1,113311












  • That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

    – sfdcfox
    4 hours ago











  • I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

    – Phil W
    3 hours ago

















  • That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

    – sfdcfox
    4 hours ago











  • I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

    – Phil W
    3 hours ago
















That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

– sfdcfox
4 hours ago





That's simply not correct. They're not passed by value; they're actively serialized, thus creating a copy. The original value was still passed in by reference.

– sfdcfox
4 hours ago













I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

– Phil W
3 hours ago





I didn't say it was pass by value, just that the original value isn't affected. I even said they are serialized and deserialize.

– Phil W
3 hours ago

















draft saved

draft discarded
















































Thanks for contributing an answer to Salesforce Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f260299%2fpass-by-reference-vs-pass-by-value%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Disable / Remove link to Product Items in Cart Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?How can I limit products that can be bought / added to cart?Remove item from cartHide “Add to Cart” button if specific products are already in cart“Prettifying” the custom options in cart pageCreate link in cart sidebar to view all added items After limit reachedLink products together in checkout/cartHow to Get product from cart and add it againHide action-edit on cart page if simple productRemoving Cart items - ObserverRemove wishlist items when added to cart

Helsingin valtaus Sisällysluettelo Taustaa | Yleistä sotatoimista | Osapuolet | Taistelut Helsingin ympäristössä | Punaisten antautumissuunnitelma | Taistelujen kulku Helsingissä | Valtauksen jälkeen | Tappiot | Muistaminen | Kirjallisuutta | Lähteet | Aiheesta muualla | NavigointivalikkoTeoksen verkkoversioTeoksen verkkoversioGoogle BooksSisällissota Helsingissä päättyi tasan 95 vuotta sittenSaksalaisten ylivoima jyräsi punaisen HelsinginSuomalaiset kuvaavat sotien jälkiä kaupungeissa – katso kuvat ja tarinat tutuilta kulmiltaHelsingin valtaus 90 vuotta sittenSaksalaiset valtasivat HelsinginHyökkäys HelsinkiinHelsingin valtaus 12.–13.4. 1918Saksalaiset käyttivät ihmiskilpiä Helsingin valtauksessa 1918Teoksen verkkoversioTeoksen verkkoversioSaksalaiset hyökkäävät Etelä-SuomeenTaistelut LeppävaarassaSotilaat ja taistelutLeppävaara 1918 huhtikuussa. KapinatarinaHelsingin taistelut 1918Saksalaisten voitonparaati HelsingissäHelsingin valtausta juhlittiinSaksalaisten Helsinki vuonna 1918Helsingin taistelussa kaatuneet valkokaartilaisetHelsinkiin haudatut taisteluissa kaatuneet punaiset12.4.1918 Helsingin valtauksessa saksalaiset apujoukot vapauttavat kaupunginVapaussodan muistomerkkejä Helsingissä ja pääkaupunkiseudullaCrescendo / Vuoden 1918 Kansalaissodan uhrien muistomerkkim

Adjektiivitarina Tarinan tekeminen | Esimerkki: ennen | Esimerkki: jälkeen | Navigointivalikko