7

I have checked many posts but still not clear. A SOQL query returns a list but if SOQL finds no records then it will return an empty list or it will be null?

When should i go for isEmpty check or when for null check?

Thanks

12

The straight SOQL accounts = [select id, .. from Account ...]

always returns a list

You can usually avoid even having to test for list empty by coding your methods to accept lists as arguments and otherwise use for loop processing as in

for (Account a: accounts) { // if accounts is empty, loop does nothing
    // do work
}

someReturnType myMethod(Account[] accounts) {
   for (Account a: account) {
      // do work
   }
}

Otherwise use accounts.isEmpty() or accounts.size() == 0

testing for null is unnecessary in a well-designed application that uses lists and maps as the core internal data structures. Personally, if I ever get a null value for a list, I prefer the null exception to occur during unit testing as it means I didn't design my code correctly to operate with lists throughout (or I forgot to init a list to empty).

N.B.

For DML, you never need to test for list empty as SFDC will do nothing if passed an empty list

Use:

update accounts; // does not burn a DML limit if list is empty

Don't use (wastes a line of code):

if (!accounts.isEmpty())
   update accounts;
  • Great!! but in the last scenario, suppose i am adding some elements to list using add method after some processing on data and finally i need to insert this list. In this case also SFDC will do nothing if passed an empty list? – R Suri Jan 7 '17 at 16:32
  • that is correct; SFDC DML methods accept lists as arguments and if list is empty, the DML statement simply returns and does not consume any limits – cropredy Jan 7 '17 at 16:34
  • OK thanks!! one last Question, In what case we can get a null list? Or when should we check for NULL on list? – R Suri Jan 7 '17 at 16:39
  • 1
    @RamanSuri No SOQL query will return a NULL list. So you'd just check for NULL if other code generated the list for you, say from an apex method you didn't code. As @cropredy mentioned in his answer, if you do generate List or Map, don't return NULL, return an empty one so that the for ( Account a : accounts ) idiom works regardless. Hope that helps! – Doug Ayers Jan 8 '17 at 0:04
  • @RamanSuri if you ever study the fflib Separation of Concerns GitHub library, you'll see that some of the best coders in the business pass lists around from method to method. – cropredy Jan 8 '17 at 0:19
6

Generally speaking, null values should be rare, and you should treat them as such. The results of a query always results in a list, even though it may be an empty list. Querying a checkbox field from the database will always be true or false, never null. Calling XmlNode.getChildElements() will never return null, but may return empty lists.

There are a few rare exceptions when you do need to check for null values. For example, when you make a variable transient, its not stored in the view state, so you usually need to implement lazy loading by checking for null first, and when you bind to a multi-select picklist, the list will always be either null or non-empty.

These are the exceptions to the rule, and you should learn them. Whenever you declare a list of your own, you should always assign a non-null value to it, which may be either a new list, or a list generated from a query. You should prefer to initialize those lists in a constructor, so that all your initialization code is in one place.

Generally speaking, when I use a method I'm not familiar with, I try calling it with a few different parameters to see if I can get a null value back instead of a list. I test it independently to verify its behavior. If it doesn't return a null, then I presume it never will. Just remember that most of the API avoids returning null values, or has a way to check beforehand. Most of the best design patterns for code avoid nulls using various techniques. As you gain experience, you'll learn those rare times when you must check for null, and find ways to code structures to reduce the null checks you need to make.

  • 1
    the one exception here is when you use "getSObjects" on a subquery that was empty it will return null.....Found that out the hard way. – Eric Jan 7 '17 at 20:57
  • @Eric I found that out the hard way too this week. Blasted getSObjects will return the dreaded null like no tomorrow. – Doug Ayers Jan 8 '17 at 0:05
  • @Eric yeah - I forgot about that one; my code even has a comment next to the null check as to why I had to insert the conditional so I didn't remove it in some future hygiene cycle – cropredy Jan 8 '17 at 0:17
  • @Eric Yeah, the problem is the SObject object. It has magical properties as long as you're still in "SObject land", which happens to operate as a null coalescing operator. For example, User u = [SELECT Manager.Manager.Manager.Id FROM User WHERE Id = :UserInfo.getUserId()]; System.debug(u.Manager.Manager.Manager.Id) won't crash, even if the user has no manager. The dynamic methods don't get that same protection. Like I said, there's some rare occurrences where you do have to watch out, but generally nulls are uncommon. – sfdcfox Jan 8 '17 at 6:41
-3

The best way is to keep a check on list size and null check both. Here is an example -

 List<Account> accList = [select id,name from account where name='test'];

 if(accList.size()>0 && accList!=null){
      //make things happen!!
    }
  • 8
    f the null check was needed (it isn't in this case) it would need to come before the size check to avoid an NPE. – Keith C Jan 7 '17 at 17:21

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.