Handling null in Java

Handling null in Java

Its a problem I encouter in most JEE projects I’ve worked on so far. Handling null-values. But why is this a problem? And what strategies can we follow to reduce the problem? That is what I’m trying to find out in this post.

Lets start with a piece of business logic, in a world where we don’t have null-values:

public BigDecimal getBalance(Person person) {
    Set<Account> accounts = person.getAccounts();
    BigDecimal totalBalance = BigDecimal.ZERO;
    for(Account account: accounts) {
        totalBalance = totalBalance.add(account.getBalance());
    }
    return totalBalance;
}

This looks good and understandable! But this isn’t what I see in most projects. Usually I see code like this:

public BigDecimal getBalance(Person person) {
	if(person != null) {
	    Set<Account> accounts = person.getAccounts();
	    if(accounts != null) {
	    	BigDecimal totalBalance = BigDecimal.ZERO;
	    	for(Account account: accounts) {
	    		if(account != null) {
	    			totalBalance = totalBalance.add(account.getBalance());
	    		}
	    	}
	    }
	    return totalBalance;
	} else {
		return null;
	}
}

Wow, that is not a pretty sight, not at all! What can we do about it and how did it happen?

Inversion of logic

The first strategy we can follow is based on inversion of logic which I’ve blogged about before. The idea is that we exit early, this will improve the readability of our method. Lets see that happens to our method is we follow this pattern:

public BigDecimal getBalance(Person person) {
	if(person == null || person.getAccounts() == null) {
		return null;
	}
	Set<Account> accounts = person.getAccounts();
   	BigDecimal totalBalance = BigDecimal.ZERO;
   	for(Account account: accounts) {
   		if(account != null) {
   			totalBalance = totalBalance.add(account.getBalance());
   		}
   	}
	return totalBalance;
}

This is somewhat better, a bit shorter, but we still have all the ‘!= null’ and ‘== null’ checks we don’t want.

Code by contract

The best way to get rid of null-checks is to get rid of nulls in your applicaties. Just don’t return a null in all of the methods…! This sounds very easy and straight forward, but it is a bit harder then it sounds because it has become such a habbit.

The good thing is that current IDE’s are implementing the @NotNull and @Nullable annotations. With these annotations you can tell other programmers, your IDE and static code analysis tools what your idea was when creating a method:

@Nullable
public Person getPerson(Long id) {
	return something.retrievePerson(id);
}
    

public void printPersonName(Long id) {
	Person person = getPerson(id);
	System.out.println(person.getName());
	//Causes warning: getPerson is Nullable, thus this is a possible NPE! 
}

It also helps you to clearly state your assumed preconditions:

public void printPersonName(@NotNull Person person) {
	System.out.println(person.getName());
	//Very good, we know we won't get a NPE here! 
}
    
    
public void executeThis() {
	Person person = null;
	printPersonName(person);
	//Causes warning: person might be null, thus can cause a NPE!
	//Code analysis tools and/or IDE will warn you about this.
}

It will also help you correct possible coding errors:

@NotNull
public Person getPersonFromDatabase(@NotNull Long id) {
	//Use JPQL
	Query query = em.createQuery("SELECT p FROM Person p WHERE p.id = :value");
	q.setParameter("value", id);
	return q.getSingleResult();
	//The IDE will complain about this. 
	//The database might return null, we don't allow returning null in this method.
}

Using this method you have some more certainties. But it isn’t a silver-bullet on its own. We have to stop and think, where do the null-values come from?

Actually, when you stop returning null (which is entirely up to you and your team) there are still situations which are ‘unchecked’. Namely external API’s, frameworks, the ORM-mapper you are using. So everywhere where you execute methods that you haven’t written, you still have to do manual checks. But make sure you do this right away. Then further on in the code, you don’t have to check anything because of your @NotNull-contracts.
If you do this to the Person object above, and all its fields, you will end up with the beautiful clean code of the first example. No checks, its just always filled by contract. The only thing you want to add is information about the parameters:

@NotNull
public BigDecimal getBalance(@NotNull Person person) {
    Set<Account> accounts = person.getAccounts();
    BigDecimal totalBalance = BigDecimal.ZERO;
    for(Account account: accounts) {
        totalBalance = totalBalance.add(account.getBalance());
    }
    return totalBalance;
}

In my experience this works very well, I’ve done this a couple of times, even before the @NotNull and @Nullable existed. Before this we would just add the information in our Javadoc. But with the IDE checking for it this has become a lot easier to use.

Null object pattern

A whole different approach then coding-by-contract is the use of a null-object. The idea behind this pattern is that you don’t return null, but instead you return a real object. In our example we would do the following:

public interface Person {

	String getName();
	void setName(String name);

	List<Account> getAccounts();
	
	//..etc..
}

public class NullPerson implements Person {
	
	public String getName() {
		return "";
	}
	
	public void setName(String name) {}

	public List<Account> getAccounts() {
		return Collections.emptyList();
	}
}

The huge advantage is that you can always safely call “person.getName()” and “person.getAccounts()” because even if you have a NullPerson the object still exists. This Null-Object is obviously usually a singleton.

public BigDecimal getBalance(Person person) {
    Set<Account> accounts = person.getAccounts();
                //NullPerson returns empty list, no more NPE!
    BigDecimal totalBalance = BigDecimal.ZERO;
    for(Account account: accounts) {
        totalBalance = totalBalance.add(account.getBalance());
    }
    return totalBalance;
}

A more elaborate but general version of this pattern is the special case pattern, named by Martin Fowler. Instead of just having a Null-special case you could also develop:

public class UnknownPerson implements Person {
	
	public String getName() {
		return "";
	}
	
	public void setName(String name) {}

	public List<Account> getAccounts() {
		return Collections.emptyList();
	}

}
public class InvalidatedPerson implements Person {
	
	public String getName() {
		return "";
	}
	
	public void setName(String name) {}

	public List<Account> getAccounts() {
		return Collections.emptyList();
	}
}

Now you can return much more information then just a meaningless “null”!

There is just one problem with this pattern. It also doesn’t just solve your problems. Why do we want to calculate the total balance of a NullPerson? The moment you retrieve a person and it is an instance of NullPerson, catch it and handle the situation appropiatly, don’t just continue.

Safe null operator

For a time there was speculation that the Safe-null-operator would make its way into Java 7 through Project Coin. If you’ve programmed in Groovy you might have seen it before:

public String getFirstLetterOfName(Person person) {
	return person?.getName()?.substring(0, 1);
}

The idea is that you use “?.” instead of “.”. The questionmark means: “If the variable we’re calling is null, the result is null, else, call the next method”.

So in this case:

  • If person is null: return null, else:
  • If getName() is null: return null, else:
  • Return result of substring(0, 1)

If you would now write this code it would be:

public String getFirstLetterOfName(Person person) {
	if(person == null) {
		return null;
	}
	if(person.getName() == null) {
		return null;
	}
	return person.getName().substring(0, 1);
}

You could also give a default value:

public void printName(Person person) {
	System.out.println(person?.getName() ?: "Anonymous");
}

If person or getName() produce a null the “?:” operator will return the default String.

Sounds pretty good eh? The only problem is that this new operator didn’t make the final list of changes for Java 7.

Fun fact: Do you know why the “?:”-operator is called the “Elvis”-operator? When viewed from the side, as smiley , it looks like Elvis. Including the big curl in his hair.