NPE as well as Null check free code ... Really ?

NPE as well as Null check free code … Really ?

NPE

Is this how your Java code review start ? NPE is always nightmare for a Java developer. Lets not discussion to much and jump on an usual Java code snippet

public interface Service {  
    public boolean switchOn(int timmer);
    public boolean switchOff(int timmer);
    //Other controls 
}
public class RefrigeratorService implements Service {
// ...
}
public class HomeServices {
    private static final int NOW = 0;
    private static HomeServices service;

    public static HomeServices get() {
        //Null Check #1
        if(service == null) {
            service = new HomeServices();
        }
        return service;
    }

    public Service getRefrigertorControl() {
        return new RefrigeratorService();
    }

    public static void main(String[] args) {
        /* Get Home Services handle */
        HomeServices homeServices = HomeServices.get();
        //Null Check #2
        if(homeServices != null) {
            Service refrigertorControl = homeServices.getRefrigertorControl();
            //Null Check #3
            if (refrigertorControl != null) {
                refrigertorControl.switchOn(NOW);
            }
        }
    }
}

Above few lines of code snippet has multiple null checks, of-course to make it robust against all possible cases. Well that is necessary but is there any better way … ? It was so often that I uses Eclipse template to surround piece of code with if condition for null check

Eclipse template for NPE check

Is there any better way ?

Well Yes !!!.
Java 8 has introduced java.util.Optional<T> . It is a container that may or may not hold non-null value. Java 8 have given safer way to handle object whose value may be null in some of the cases. It is inspired from the ideas of Haskell and Scala.

In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional<T> class forces you to think about the case when the value is not present. As a consequence, you can prevent unintended null pointer exceptions.

In above example we have home service factory that returns handle to multiple appliances available in the home. But these services may or may not available/functional, it means it may result NullPointerException. Instead of adding null if condition before using any service, let wrap it in to Optional<Service>.

Wrapping to Option<T>

Lets consider method to get reference of service from factory, instead of returning the service reference wrap it with Optional. It let the API user know that the returned service may or may not available/functional, use defensively

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

As you see Optional.ofNullable() provides easy way to get the reference wrapped. There are another ways to get reference of Optional , either Optional.empty() & Optional.of(). One for returning empty object instead of retuning null and other to wrap non-nullable object, respectively.

So how exactly it helps to avoid null check ?

Once you have wrapped reference object, Optional provide may useful methods to invoke methods on wrapped reference without NPE.

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

Optional.ifPresent invoke the given Consumer with reference if it is non-null value otherwise does nothing.

@FunctionalInterface
public interface Consumer<T>
Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.

It is so clean and easy to understand. In the above code example, HomeService.switchOn(Service) gets invoked if the Optional holding reference is non-null.

We user ternary operator very often for checking null condition and return alternative value or default value. Optional provides another way to handle same condition without checking null. Optional.orElse(defaultObj)returns defaultObj if the Optional has null value. Lets use this in our sample code

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

Now HomeServices.get() does same thing but in better way. It checks whether the service is already initialize of not. If it is then return same or create new New service. Optional<T>.orElse(T) helps to return default value.

Finally here is our NPE as well as null check free code

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

    public static Optional<HomeServices> get() {
        service = Optional.of(service.orElse(new HomeServices()));
        return service;
    }

    public Optional<Service> getRefrigertorControl() {
        Service s = new  RefrigeratorService();
        //...
        return Optional.ofNullable(s);
    }

    public static void main(String[] args) {
        /* Get Home Services handle */
        Optional<HomeServices> homeServices = HomeServices.get();
        if(homeServices != null) {
            Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
            refrigertorControl.ifPresent(HomeServices::switchItOn);
        }
    }

    public static void switchItOn(Service s){
        //...
    }
} 

Source :
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Cartoon Image source : http://geek-and-poke.com/

Comments

Post a Comment

Popular posts from this blog

State Design Pattern by Example

HashMap hashCode collision by example

How to avoid NPE while Auto-Unboxing