3

This is a more general computer science question -hope those are ok to ask here. As a self-taught Salesforce dev I have been trying to work on my core computer science knowledge. I am working on pointers and passing by reference vs value right now.

In the documentation, it says that all primitive values are passed by value. I wrote the following trivial program below to swap integer values and it behaves exactly as I would expect. Inside the function, the values change but the values for the original Integer x and y do not.

Is there a way in Apex to change the value of the original variable? The way you can use an int * in C?

public with sharing class Swapper {

    public static void swapInteger(Integer x, Integer y){
        Integer tempInteger = x;
        x = y;
        y = tempInteger;

        System.debug('value of x in function ' + x);
        System.debug('value of y  in function ' + y);
    }
}

test class

@IsTest
private class Swapper_Test {
    @IsTest
    static void swapTest() {
        Integer x = 5;
        Integer y = 10;
        Swapper.swapInteger(x , y);

        System.assertEquals(5, y);
        System.assertEquals(10, x);
    }
}
3

In Apex, everything is pass-by-value, and all variables only store references. You might say that parameters are passed by reference-value. This is different than some other languages, where you might pass by reference or by value, and it kind of muddies the waters a bit.

The value of each variable is copied when provided as a parameter, but since Apex only uses references, what you get is a copy of a reference; if the object is not immutable, it can be modified to a new value. The original variable that held the reference, however, cannot be modified by the callee (which is what is typically meant by passing by reference).

All you really need to know is that there's no way to get a reference to a variable directly, you can only get references to objects on the heap. There is no way to write this type of code in Apex without using an object of some sort:

class TwoValues {
  Integer x, y;
}
public void swapTwoValues(TwoValues items) {
  Integer temp = items.y;
  items.y = items.x;
  items.x = temp;
}
...
TwoItems item = new TwoItems();
item.x = 5;
item.y = 10;
swapTwoValues(item);
3

As far as i understand salesforce is based on Java or at least follows the concepts of JAVA and java supports Pass by value.

2nd point is that pass by reference is a complex concept whole concept of salesforce is to focus on less coding means less developer skills so it is not feasible to provide such difficult features.

3rd point is that you are always allowed to create public variable or class level variables which you can access in different methods, hence no need of passing by reference.

1

A very good example of this topic is provided on the Passing Parameters By Reference and By Value in Apex documentation. Everything in Apex is passed-by-value. The docs mentions as below (emphasis mine):

As described in the new developer’s guide text, Apex is not passing anything by reference. It is passing the reference (i.e., the memory address) by value, which allows the developer to change fields on the object and call methods (like list.add()) on the object

The doc contains example around this.

As an example, in the below class, the two methods reflect this behavior.

public class PassByExample {

    /**
     * this change in the passed list will be always known to the caller
     * the memory address was passed-by-value
     * the caller will always have the original memory address and thus the values
     */
    public static void passByValueChange(List<String> lstString) {
        lstString.add('This was added in the method');
    }

    /**
     * this change in the passed list will be NOT known to the caller
     * the memory address was passed-by-value; but changed in the method
     * the caller will always have the original memory address and NOT the new one
     */
    public static void passByValueNoChange(List<String> lstString) {
        lstString = new List<String>(); // memory address was changed
        lstString.add('This was additionally added in the method');
    }
}

Now, when you test this out:

@isTest static void testPassByValueChange() {
    List<String> lst = new List<String>();
    lst.add('Added from test class');

    PassByExample.passByValueChange(lst);
    system.debug(lst); // debugs (Added from test class, This was added in the method)
    system.assertEquals(2, lst.size());
}

@isTest static void testPassByValueNoChange() {
    List<String> lst = new List<String>();
    lst.add('Added from test class');

    PassByExample.passByValueNoChange(lst);
    system.debug(lst); // debugs (Added from test class)
    system.assertEquals(1, lst.size());
}
  • passByValueNoChange should only show "Added from test class" and size should be 1. – sfdcfox May 14 at 16:57
  • That was a copy paste mistake. And for the size, the snippet was run from the same test method, thus 2. – Jayant Das May 14 at 16:59
  • Fair enough, though the example might cause some confusion. Perhaps make it something a bit more obvious? – sfdcfox May 14 at 17:01
  • Fair point. Updated to reflect different test methods now. – Jayant Das May 14 at 17:05

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.