What is a variable? Are they passed By Value or By Reference? - El Toro - Find articles about Visualforce, Apex, Force.com and Salesforce in general

Print Preview

What is a variable? Are they passed By Value or By Reference?

You may have seen or even written code like this:

String myString;
myString = 'Hello World!';

But do you know what goes inside a simple statement like this? Before we can start talking about this code, we need to understand how the values are stored in memory. This table will help me explain some of the basic concepts:

Address 0x0 0x1 0x2 0x3 0x4 0x5 0x6
Data Hello World! 35 9.78 2013-SEP-01 Wednesday 0x6
One
Two
Three

This table represents the memory used by a program, which can be illustrated with boxes accessible with their own address. The value of each box is shown on the bottom row, and each box address can be seen on the top row (in hexadecimal value, for example 0x3). The contents of each box can have any type of data, like strings, numbers, dates or as show in box 0x5 addresses of other boxes (this is going to be very important for a later discussion).

Let’s go back to our original code, and try to answer the original question… What is going on inside this simple line of code?

String myString;
myString = 'Hello World!';

On the first line, we are assigning the name “myString” to the box at address 0x1. It’s a lot easier to use names, rather that long cryptic address… On the second line, we are instructing the application to put the value 'Hello World!' inside the box that we are calling “myString”.

I know what you are thinking… So what? I had this clear in my head without thinking about boxes and hexadecimal codes. Why is this important?

Let me start giving you some more pieces of code that could be confusing. First, let’s think about this code:

String myString;
String myOtherString;
myString = 'Hello World!';
myOtherString = myString;
myString = 'New Value';

What is the value for myString? What is the value for myOtherString? Do they have the same value? If we think about boxes, then it is clear what is going on. 

  • Line #1: Create a box called “myString”, let’s say this box has the address 0x1.
  • Line #2: Create another box named “myOtherString” with address 0x2. As you can see, we have two different boxes.
  • Line #3: Put 'Hello World!' on box 0x1 (myString).
  • Line #4: Copy the value from box 0x1 (myString) to box 0x2 (myOtherString).
  • Line #5: Put 'New Value' in box 0x2 (myOtherString).
At the end of this code, our boxes look like this:

Address 0x0 0x1
Data New Value Hello World!

If this makes sense, then we could go one level higher with our code. Let’s think about this now:

public void myMethod(String myParameter) {
	System.debug(myParameter);
	myParameter = 'Changed inside the method';
	System.debug(myParameter);
}
String myString;
myString = 'Hello World';
myMethod(myString);
System.debug(myString);

What is the value of “myString” after returning from the method? Again let’s think in terms of boxes to help this be clearer:
  • Line #6: Create a box called “myString” at address 0x1.
  • Line #7: Put 'Hello World' inside the box 0x1
  • Line #8: Call the method and pass the value of the box 0x1, in this example is 'Hello World'. It is very important to understand that we do not pass the address of the box (0x1) but the value contained inside the box 'Hello World'. This is what is known as “Passed By Value”.
  • Line #1: Create a box named “myParameter”, addressed as 0x2, and put the value 'Hello World' in this box.
  • Line #2: Prints the value of the box 0x2, which will be 'Hello World'.
  • Line #3: Put 'Changed inside the method' inside box 0x2 (“myParameter”). Note we are not changing the box 0x1, but only box 0x2.
  • Line #4: Prints the value of the box 0x2, which will be 'Changed inside the method'.
  • Line #9: This is the next line executed after the method completes, and it prints the value of the box 0x1 named “myString”. Remember that we changed the value of the other box ;-)
This is what the boxes look like just before the method returns:

Variable myString myParameter
Address 0x1 0x2
DataHello World Changed inside the method

Let’s look at another example, and think if the output at line 12 is the same as the output at line 10 or the output at line 4?

public void myMethod(List<String> myParameter) {
	System.debug(myParameter.size());
	myParameter.add('Three');
	System.debug(myParameter.size());
}
List<String> myStrings;
myStrings = new List<String>();
myStrings.add(‘One’);
myStrings.add(‘Two’);
System.debug(myStrings.size());
myMethod(myStrings);
System.debug(myStrings.size());

Careful, I just threw at you a curve ball… The answer may not be as obvious as it looks. Before I can explain what is happening with this code, I need you to go back at the first set of boxes and notice that boxes can contain strings, numbers, dates, but some boxes contains addresses for other boxes!

Apex calls “primitive data types” those variables that have plain values in the boxes which are: Blob, Boolean, Date, Datetime, Decimal, Double, ID, Long, String and Time. The other data types do not have the value stored in the box, but rather they store the address of another box. With this in mind, let’s examine the previous code.
  • Line #6: Create a box called “myStrings”, in the table shown before this will be addressed at 0x1.
  • Line #7: Create a new list of Strings and store that list in box 0x3, the code also puts this address in box 0x1. The runtime engine knows that if the box contains an address the real data is referenced through the address given.
  • Lines #8, 9: Adds 2 values to the list in box 0x3. Notice that box 0x1 is not changed, since it only contains an address.
  • Line #10: Prints the size of the list referenced by 0x1, in our case the list is located at 0x3 and has 2 elements.
  • Line #11: Call the method and pass the value of the box 0x1, in this example it will be the address 0x3. Note, here we are not passing the actual list to the method (that would be too much information to copy over), we are just passing the address where the list can be found and the runtime engine knows the value needs to be referenced by the address we are passing.
  • Line #1: Create a box named “myParameter”, addressed as 0x2, and put the value 0x3 in this box.
  • Line #2: Prints the size of the list referenced by the box 0x2, in our case the list is located at 0x3 and has 2 elements.
  • Line #3: To the list in 0x3 (referenced by the box 0x2) add the new value 'Three'.
  • Line #4: Prints the size of the list in 0x3 (referenced by the box 0x2), in our case has 3 elements.
  • Line #12: This is the next line executed after the method completes, and it prints the value of the list in box 0x3 (referenced by box 0x1). Because box 0x1 and 0x2 reference the same list (at box 0x3) and this list was modified in the called method, the value printed is 3.
This is what the boxes look like just before the method returns:

Variable myStrings myParameter  
Address 0x1 0x2 0x3
Data 0x3 0x3
One
Two
Three

There are two parts to this explanation that are not mandatory to understand in order to be successful with the code you write, but that I think are important for the completeness of this article:
  • There are 2 types of memory: “Heap Memory” and “Stack Memory”. In our example, boxes 0x1 and 0x2 are located on the “Stack Memory” but box 0x3 is located on the “heap Memory”. All the variables that are defined inside a method, including the parameters, are stored in the “Stack Memory” and will be automatically destroyed at the end of the method call, on the other hand, boxes that are located in the “Heap Memory” will be “garbage collected” when they are no longer needed.
  • Some people (incorrectly) call this “Passed By Reference”, because we are passing an address that the runtime engine needs to reference in order to get the value needed. But if you pay attention to what is going on, this is passing the value of the box 0x1 (no different as to what happened when we passed a the value of a box that happened to be a string), what is different here is how this value is being used. On the case of the string, we were passing the real value, but here the value is used as an address to get to the value needed. Sure, it happens to be the reference to another box (0x3) but it is the value of the box 0x1!
A final note on these boxes, is that when you look at the value of your variables in the Developer Console, you will see some values and some codes… These codes are the actual addresses of the other boxes. If you were to run this code in the Developer Console:
 

// Primitives
Boolean primBoolean = true;
Date primDate = Date.Today();
DateTime primDateTime = DateTime.Now();
Decimal primDecimal = 1;
Double primDouble = 2;
ID primID = [SELECT ID FROM Account LIMIT 1].ID;
Integer primInteger = 3;
Long primLong = 4;
String primString = 'Hello World';
Time primTime = Time.newInstance(23,59,59,999);
//Blob primBlob = Blob.valueOf(primString);

// Collections
List<String> collList = new List<String>();
Map<String, String> collMap = new Map<String, String>();
Set<String> collSet = new Set<String>();

// sObject
sObject sobjBase = [SELECT ID FROM Account LIMIT 1];
Account sobjAccount = (Account) sobjBase;
Position__c sobjPosition = [SELECT ID FROM Position__c LIMIT 1];

You would see the variables panel contain hexadecimal codes for the boxes that contain addresses:

comments powered by Disqus

© El Toro . IT @ 2013
Andrés Pérez