How To Avoid NullPointerException? 1 - Should we allow Null?

HowToAvoidNPE1

How to avoid NullPointerException 1 - Should We Allow Null?

NullPointerException(NPE) is the most common type of Exception we face in Java. How can we avoid NPE?
Consider the following example:

public class BankAccount {
	private Integer accountId;
	private String owner;
	private BigDecimal balance;
    // Getter Setter
}
public class BankService {
	public void transferAmountTo(BankAccount from, BankAccount to, BigDecimal amount) {
		from.setBalance(from.getBalance().subtract(amount));
		to.setBalance(to.getBalance().add(amount));
	}
}

What will you do when you see NPE when executing transferAmountTo?

Null Check

This is almost the first thing we do when we see NPE.

	public void transferAmountTo(BankAccount from, BankAccount to, BigDecimal amount) {
		if (from != null) {
			if (to != null) {
				if (from.getBalance() != null) {
					if (to.getBalance() != null) {
						if (amount != null) {
							from.setBalance(from.getBalance().subtract(amount));
							to.setBalance(to.getBalance().add(amount));
						}
					}
				}
			}
		}
	}

You may feel safe about this. But it is probably the worst way to solve NPE, as

  1. The nested if statement is difficult to read.
  2. This may hide programming error created in upstream, we always want to find the bug earlier.

So what should you do when you see NPE?

Why Null?

You should ask

  1. Why from/to is null?
  2. Why amount is null?
  3. Why getBalance return null?

Are they supposed to be null? For 1 and 2, I will answer “NO”. IMO, method parameter should not be null by default. We should reduce occurrence of null as much as possible as null is the ROOT cause of NPE.
For 3, “NO” also. You may argue “What if the account is not ready yet?”, I would say “Do you expect to see balance: null in your bank account?”. Just like primary key of a table, name of a person, size of a file, these property are supposed not nullable. In our example. it is natural to set the balance to 0 by default, instead of null.

Solution

So we will assume the parameters are not null and it will be the caller’s responsibility to ensure the parameters are valid. But it is our work to let caller to find the problem easily. and to express our assumption clearly.

	public void transferAmountTo(BankAccount from, BankAccount to, BigDecimal amount) {
		if (from == null) {
			throw new IllegalArgumentException("from should not be null");
		}
		if (from.getBalance() == null) {
			throw new IllegalArgumentException("from.getBalance() should not be null");
		}
		if (to == null) {
			throw new IllegalArgumentException("to should not be null");
		}
		if (to.getBalance() == null) {
			throw new IllegalArgumentException("to.getBalance() should not be null");
		}
		if (amount == null) {
			throw new IllegalArgumentException("amount should not be null");
		}
		from.setBalance(from.getBalance().subtract(amount));
		to.setBalance(to.getBalance().add(amount));
	}

Feel free to put any comment.

Comments