If you’re a Salesforce admin, you’ve probably seen the dreaded System.NullPointerException: Attempt to de-reference a null object
at some point in time.
I tried to find the official documentation about how Apex handles null values in memory - but I couldn't. The following lesson is a hybrid of both Apex specific and general explanations of how null
works in languages like Java.
Null
is a special keyword in Apex that can be assigned to any type. Let’s say you have a simple variable declaration and assignment command:
String firstName = 'Jerry';
We’ve declared a variable with the datatype String, assigned the identifier firstName
, and initialized it with the literal ‘Jerry’. This tiny command alters the computer’s disk. Space is allocated in memory that’s big enough to hold a String. The firstName
identifier points to this memory address to keep track of it. The value ‘Jerry’ is stored at this memory address.
What would happen if we reassigned firstName to null
?
firstName = null;
In languages like Java, the String ‘Jerry’ still exists in memory, but the identifier firstName
is no longer referencing it. firstName
is now referencing nothing. There is no memory address being referenced by firstName
. Null represents the absence of a memory address. Eventually, the garbage collector, a special piece of software that runs automatically, will detect that there are no pointers referencing this data and it will delete the value held in memory.
Let’s expand on this with some other scenarios:
String firstName = 'Jerry'; String middleName = null’ String lastName;
We know the first line allocates memory on the disk and identifies it with the firstName
identifier. We know the second line creates a pointer named middleName
but doesn’t assign a memory address to it. But what about the last line?
The difference here is that null is not explicitly assigned, but lastName
is still a pointer that points to no data. The perceived result is the same as explicitly assigning null.
This is very different than assigning a String like this:
String lastName = '';
Here, a pointer called lastName
is created and used to reference a memory address. It just so happens that there’s no data in the memory address that’s been allocated.
What’s the impact here, and where does “de-reference a null object” come in? Let’s use Apex’s String Class and it’s capitalize()
method to show you:
String firstName = 'Jerry'; firstName = firstName.capitalize(); // firstName is now JERRY
The code above works because firstName
references real data at an actual memory address. If firstName
was null, this wouldn’t work:
String firstName; String capitalizedFirstName = firstName.capitalize(); //throws a runtime exception for de-referencing a null object
Referencing is the act of assigning a pointer to an address. De-referencing is the act of retrieving the from that memory address. This throws a null pointer exception because firstName
is null. It’s the equivalent to String capitalizedFirstName = null.capitalize();
. Apex attempts to find a reference to capitalize()
within null
, but null doesn’t point to a real memory address - so 🧨, the code halts and returns a runtime error with that message.
The code below will not throw an exception. An empty memory address data is not the same as no memory address.
String firstName = ''; String capitalizedFirstName = firstName.capitalize();