A better approach to handle Java NullPointerException



The most common exception that you meet coding in java whether you are a junior or an Intermediate level programmer. Before coming to the solution proposed and added in the new Java update, I would like to discuss the strategies that most of us should follow while handling this common but peculiar exception. There are two approaches that people generally follow.

1.) Treat Null as a valid response
2.) Treat Null as an invalid response

Life is very easy for the people who go with the second approach. Taking null as an invalid response you won't be getting a null reference calling any of your methods or API. So where there is a situation where null is to be handled, throw InvalidArgumentException or try assert. Assert throws an exception whenever the condition given to it is false. And in case you are using collections always return an empty collection instead of null reference

But most of you will disagree going with the second approach since most of us have been using the first approach from the very start. You have been using APIs where you don't have the control over the code. Now with the first case you never know where you are going to meet with null reference. So you have nothing left except a valid check for the null reference.

Solutions to Valid Null Checks
  1. Depending upon what kind of objects you are checking you may be able to use some of the classes in the apache commons such as: apache commons lang and apache commons collections

    Example:

    String name;
    ...
    if( StringUtils.isBlank( name) ) {
    ///do something
    }

    or (depending on what you need to check):

    String name;
    ...
    if( StringUtils.isEmpty( name) ) {
    ///do something
    }

    The StringUtils class is only one of many; there are quite a few good classes in the commons that do null safe manipulation.
  2. If you switch to JetBrains Idea, a Java ide, you can use some annotations developed by them.
    Basically, you've got:
    @Nullable
    and
    @NotNull
    You can use these annotations in method and parameters, like this:
    @NotNull public String getName() {
    return "Saurab Parakh";
    }
    
    
    When you use the first getName() function in this way:
    public static void main(String[] args)
    {
    if(getName() != null) {
    System.out.println(getName());
    }
    }
    Now the JetBrains idea compiler will tell you that the null check is useless, since the getName() will never return null. Using parameter
    void someMethod(@NotNull someParameter) { }
    if you write something like:
    someMethod(null);
    This won't compile.

Other Proposed Solutions from Java 7
 
The original idea comes from groovy. It was proposed for Java 7 as part of Project Coin: https://wikis.oracle.com/display/ProjectCoin/2009ProposalsTOC, (Elvis and Other Null-Safe Operators) but hasn't been accepted yet.

Null Safe Operators
Elvis or other null safe operators to get every NPE handled.

i) Elvis Operator
It results to the value on the left hand side if not null else right hand side is evaluted.
Example:
Integer a = getInteger();  // may be null
int i = a ?: -1;  // no NPE from unboxing  
So here the value of a will be assigned to i only if a is not equal to null.

ii) Null Safe operator
It is similar to member selection dot operator(.). Just a valid null check is added to its definition.
Example:
class Student {    private Parent parent; // may be null
public Parent getParent() {
return this.parent;    }
} class Parent {     String name; // may be null
private Address address; // may be null
public Address getAddress () {
return this.address;    }
}
class Address {
private String locaton;
private private String street;
String houseNumber;
public String getLocation () {
return this.location;    }
}

So without this feature you would have written something like this
String location= null;
if (student != null && student.getParent() != null && student.getParent().getLocation != null) {
location= student.getParent().getLocation();
} else {
location= "unknown";
}

But with Java's Null safe operator your code can be eased down to something like this.
String location = student?.getParent()?.getLocation() ?: "unknown";

So what are the major benefits and disadvantages of these features.

Advantages
  • Since the null checks get automatically handled with the use of these operators so now one can focus more on the business logic.
  • Code size and complexity gets reduced
Disadvantages
  • It encourages rather than discouraging the use of null reference in the APIs.
But as we know this feature is not accepted yet, we need to stick to other solutions available as discussed in post above.
 So how did you find the post? Please share your reviews about the post.
Submit this post on reddit

Related

java 5439294094922684881

Post a Comment

  1. I like to keep nulls out of my code as much as possible. If a null return value from one of my methods is unavoidable then I like to add OrNull to the end of the method name. For example, findItemOrNull() would return the item if it could find it, or null if it wasn't there. The method name makes the code obviously suspicious if the caller doesn't do a null check before it uses the return value.

    ReplyDelete
  2. I'm so in the second group.

    ReplyDelete
  3. You can write the sample code in a more concise form using Java 6 e.g.:

    String location = "unknown";
    if (student != null && student.getParent() != null && student.getParent().getLocation() != null)
    location = student.getParent().getLocation();

    or even with a one liner:

    String location = student != null ? (student.getParent() != null ? student.getParent().getLocation() : "unknown") : "unknown";

    ReplyDelete
  4. @Chris Foley: Thats good. Prevention is always better than cure. But only a few people do so.

    ReplyDelete
  5. @Kikito: Not only you Kikito, most of us fall in that category

    ReplyDelete
  6. @marko asplund: Yes you are absolutely right. Using ternary operator would have made the code more concise. And even initializing with the value in the else case could have reduced the block of code. That shows how much concerned you are about the code optimization.

    ReplyDelete
  7. Indeed, these would be more helpful if the features had actually made it into Java 7.

    ReplyDelete
  8. I'm a big fan of NullPointerExceptions!

    Particularly, I don't see the use of _avoiding_ and masking NPEs using code like the above, it just makes the problem worse....

    The vast majority of time that code encounters an _unexpected_ (or invalid) NULL value, it is due to a bug in the code.

    In that case, the best thing is not to _avoid_ the NPE but to let it blow up at the exact line of code that is causing the problem, with a pretty stack trace that will instantly show what is wrong.

    It gets the bug fixed quickly and it makes the code clean because the code just says what it wants to do.

    If you avoid NPEs as in the code above, the program will _eventually_ do something wrong (because of the very real bug), but by the time it actually fails you will not know what caused it and have to go back through umpteen hundred lines of code searching for the thing that didn't execute and caused the failure. (Oh, the Row is empty because the Context was null because the Bean doesn't exist because the FactoryFactory never had it's orange juice injected and none of them ever bothered to tell me, grrr...)

    Now, if you have a system where you don't want it to stop running, well, you can handle the exception. Better still is a general exception handling framework that works across the system and handles/logs _all_ unexpected exceptions.

    ReplyDelete
  9. Instead of passing around primitive objects (ie: String, Long, Integer, etc) create and use value objects. Do not allow the value objects to be created with null parameters.

    For example, the location in Marko's example is a String but it could be wrapped in a value object named Location which just wraps String. The constructor or factory method would simply throw an example as soon as someone tried to pass null to Location. Downstream client code, again such as Marko's, would have to concern itself with null checking and just get on with business. When someone did try to pass a null to Location it would be in a more appropriate location to handle the invalid data.

    The creation and use of value objects is far cheaper than handling null throughout your code base.

    Seamus

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. @MarkoAsplund
    Your simple line can be more simple as

    String location = student != null && student.getParent() != null && student.getParent().getLocation()!=null ? student.getParent().getLocation() : "unknown";

    By the way loved your post @Saurab!

    ReplyDelete
  12. no where in your post you mentioned about the java version :(

    ReplyDelete
  13. postingan yang anda buat bagus,,,,,,,,,

    ReplyDelete

emo-but-icon

Translate

 

Recent Posts

comments

Recent Comments Widget

Join Us

 

Sponsored By

Recommended for you

get social

item