Null Coalescing Operator

The ?? operator returns its right-hand side operand when its left-hand side operand is null. Similar to the safe navigation operator (?.), the null coalescing operator (??) replaces verbose and explicit checks for null references in code.

The null coalescing operator is a binary operator in the form a ?? b that returns a if a isn’t null, and otherwise returns b. The operator is left-associative. The left-hand operand is evaluated only one time. The right-hand operand is only evaluated if the left-hand operand is null.

You must ensure type compatibility between the operands. For example, in the expression: objectZ result = objectA ?? objectB, both objectA and objectB must be instances of objectZ to avoid a compile-time error.

Here’s a comparison that illustrates the operator usage. Before the Null Coalescing Operator, you used:

1Integer notNullReturnValue = (anInteger != null) ? anInteger : 100;

With the Null Coalescing Operator, use:

1Integer notNullReturnValue = anInteger ?? 100;

While using the null coalescing operator, always keep operator precedence in mind. In some cases, using parentheses is necessary to obtain the desired results. For example, the expression top ?? 100 - bottom ?? 0 evaluates to top ?? (100 - bottom ?? 0) and not to (top ?? 100) - (bottom ?? 0).

Apex supports assignment of a single resultant record from a SOQL query, but throws an exception if there are no rows returned by the query. The null coalescing operator can be used to gracefully deal with the case where the query doesn’t return any rows. If a SOQL query is used as the left-hand operand of the operator and rows are returned, then the null coalescing operator returns the query results. If no rows are returned, the null coalescing operator returns the right-hand operand.

Salesforce recommends against using multiple SOQL queries in a single statement that also uses the null coalescing operator.

Warning

These examples work with Account objects.

1Account defaultAccount = new Account(name = 'Acme');
2// Left operand SOQL is empty, return defaultAccount from right operand:
3Account a = [SELECT Id FROM Account 
4   WHERE Id = '001000000FAKEID'] ?? defaultAccount;
5Assert.areEqual(defaultAccount, a);
6
7
1
2// If there isn't a matching Account or the Billing City is null, replace the value
3string city = [Select BillingCity 
4    From Account 
5    Where Id = '001xx000000001oAAA']?.BillingCity;
6System.debug('Matches count: ' + city?.countMatches('San Francisco') ?? 0 );

Usage

There are some restrictions on using the null coalescing operator.

  • You can’t use the null coalescing operator as the left side of an assignment operator in an assignment.
    • foo??bar = 42;// This is not a valid assignment
    • foo??bar++; // This is not a valid assignment
  • SOQL bind expressions don’t support the null coalescing operator.
    1class X { public String query = 'xyz';} 
    2X x = new X(); 
    3List<Account> accounts = [SELECT Name FROM Account WHERE Name = :X??query]
    4List<List<SObject>> moreAccounts = [FIND :X??query IN ALL FIELDS 
    5    RETURNING Account(Name)];