Java
Following examples shows how to avoid NullPointerException within chained method calls.
Examples
Example POJOs
package com.logicbig.example;
public class Person {
private Address address;
.............
static Person getPerson(){
Person person = new Person();
Address address = new Address();
person.setAddress(address);
return person;
}
}
package com.logicbig.example;
public class Address {
private City city;
.............
}
package com.logicbig.example;
public class City {
private String name;
.............
}
Calling chained methods
package com.logicbig.example;
public class Example {
public static void main(String[] args) {
String name = Person.getPerson().getAddress().getCity().getName();
System.out.println(name);
}
}
Exception in thread "main" java.lang.NullPointerException at com.logicbig.example.Example.main(Example.java:6)
Fixing with if bocks
package com.logicbig.example;
public class Example2 {
public static void main(String[] args) {
String cityName = null;
Person person = Person.getPerson();
if (person != null) {
Address address = person.getAddress();
if (address != null) {
City city = address.getCity();
if (city != null) {
cityName = city.getName();
}
}
}
if (cityName == null) {
cityName = "N/A";
}
System.out.println(cityName);
}
}
N/A
By using java.util.Optional
package com.logicbig.example;
import java.util.Optional;
public class Example3 {
public static void main(String[] args) {
String name = Optional.of(Person.getPerson())
.map(Person::getAddress)
.map(Address::getCity)
.map(City::getName)
.orElse("N/A");
System.out.println(name);
}
}
N/A
Creating reusable util methods with Optional
We can create util methods which can use java.util.Optional API internally:
package com.logicbig.example;
import java.util.Optional;
import java.util.function.Function;
public class NullSafeUtil {
public static <R, T, A> R eval(R defaultValue, T input,
Function<T, R> function) {
return Optional.ofNullable(input)
.map(function)
.orElse(defaultValue);
}
public static <R, T, A> R eval(R defaultValue, T input,
Function<T, A> function,
Function<A, R> function2) {
return Optional.ofNullable(input)
.map(function)
.map(function2)
.orElse(defaultValue);
}
public static <R, T, A, B> R eval(R defaultValue, T input,
Function<T, A> function,
Function<A, B> function2,
Function<B, R> function3) {
return Optional.ofNullable(input)
.map(function)
.map(function2)
.map(function3)
.orElse(defaultValue);
}
public static <R, T, A, B, C> R eval(R defaultValue, T input,
Function<T, A> function,
Function<A, B> function2,
Function<B, C> function3,
Function<C, R> function4) {
return Optional.ofNullable(input)
.map(function)
.map(function2)
.map(function3)
.map(function4)
.orElse(defaultValue);
}
//more overloaded methods
}
package com.logicbig.example;
public class Example4 {
public static void main(String[] args) {
String cityName = NullSafeUtil.eval("N/A", Person.getPerson(),
Person::getAddress, Address::getCity, City::getName);
System.out.println(cityName);
City city = NullSafeUtil.eval(null, Person.getPerson(),
Person::getAddress, Address::getCity);
System.out.println(city);
Address address = NullSafeUtil.eval(null, Person.getPerson(),
Person::getAddress);
System.out.println(address);
}
}
N/A null Address{city=null}
By catching NullPointerException
package com.logicbig.example;
import java.util.function.Supplier;
public class NullSafeUtil2 {
public static <R> R eval(Supplier<R> chainSupplier, R defaultValue){
try {
return chainSupplier.get();
} catch (Exception e) {
return defaultValue;
}
}
}
package com.logicbig.example;
public class Example5 {
public static void main(String[] args) {
String cityName = NullSafeUtil2.eval(() -> Person.getPerson().getAddress().getCity().getName(), "N/A");
System.out.println(cityName);
City city = NullSafeUtil2.eval(() -> Person.getPerson().getAddress().getCity(), null);
System.out.println(city);
Address address = NullSafeUtil2.eval(() -> Person.getPerson().getAddress(), null);
System.out.println(address);
}
}
N/A null Address{city=null}
Note that, allowing runtime exception is considered to be relatively expensive process than to avoid it. It is due to the fact that throwing exceptions require
various stacktrace objects to be initialization.
|