Null is a headache for Java programmers. It is often plagued by null-pointer exceptions (NPE). Even the inventor of Java admits this was a big mistake.

So, what can you do to avoid writing a lot of nulls in your code?

Some people say that you can use the Optional option provided by JDK8 to avoid short betting, but it is still a bit cumbersome to use.

In daily work, the author encapsulates a tool that can chain call object members without nullify. Compared with the original if NULL logic and Optional provided by JDK8, it is more elegant and easy to use. In engineering practice, it greatly improves the coding efficiency, and also makes the code more accurate and elegant.

The air conditioner is used inelegantly

I’m sure any Java developer has encountered the following annoying null-judgment logic: There is now a User class whose member variable is School

/** * @author Axin * @since 2020-09-20 * @summary */ @data public class User {private String name; */ @data public class User {private String name; private String gender; private School school; @Data public static class School { private String scName; private String adress; }}Copy the code

Now we want to get the School member variable adress.

public static void main(String[] args) { User axin = new User(); User.School school = new User.School(); axin.setName("hello"); if (Objects.nonNull(axin) && Objects.nonNull(axin.getSchool())) { User.School userSc = axin.getSchool(); System.out.println(userSc.getAdress()); }}Copy the code

The Optional tool is also available via JDK8, but it is still a bit troublesome.

Optionalbeans below provide a way to continuously chain calls to member variables without nulling them, directly to the target variable you want to fetch without worrying about null Pointers.

Chain calls member variables

If you use the tool OptionalBean designed in this article, the above call can be simplified as follows:

public static void main(String[] args) { User axin = new User(); User.School school = new User.School(); axin.setName("hello"); String value1 = optionAlBean.ofNullable (axin).getBean(User::getSchool) .getBean(User.School::getAdress).get(); System.out.println(value1); }Copy the code

Execution Result:

Where the school variable of User is null, you can see that the code does not have a null pointer, but returns null. How does this tool work?

OptionalBean tools

/** * @author Axin * @since 2020-09-10 * @summary */ public Final class OptionalBean<T> {private static final OptionalBean<? > EMPTY = new OptionalBean<>(); private final T value; private OptionalBean() { this.value = null; } @param value */ private OptionalBean(T value) {this.value = objects.requirenonNULL (value); } public static <T> OptionalBean<T> of(T value) {return new OptionalBean<>(value); Public static <T> OptionalBean<T> ofNullable(T value) {public static <T> OptionalBean<T> ofNullable return value == null ? empty() : of(value); } @param fn * @param <R> * @return */ public T get() {return objects.isnull (value)? null : value; Public <R> OptionalBean<R> getBean(Function<? super T, ? extends R> fn) { return Objects.isNull(value) ? OptionalBean.empty() : OptionalBean.ofNullable(fn.apply(value)); } @param other @return */ public T orElse(T other) {return value! = null ? value : other; } /** * Public T orElseGet(Supplier<? extends T> other) { return value ! = null ? value : other.get(); } /** * Throws an exception if the target value is empty * @param exceptionSupplier * @Param <X> * @return * @throws X */ public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { if (value ! = null) { return value; } else { throw exceptionSupplier.get(); } } public boolean isPresent() { return value ! = null; } public void ifPresent(Consumer<? super T> consumer) { if (value ! = null) consumer.accept(value); } @Override public int hashCode() { return Objects.hashCode(value); Public static<T> OptionalBean<T> Empty () {@suppressWarnings ("unchecked"); OptionalBean<T> none = (OptionalBean<T>) EMPTY; return none; }}Copy the code

The tool design mainly refers to the Optional implementation, plus the extension to the chain call is the above OptionalBean.

GetBean actually returns an OptionalBean object wrapped around an empty value when the variable is null, and the use of generics makes the tool easier to use.

The manual

You can see that the code also provides the same extension methods as Optional, such as ifPresent(), orElse(), and so on:

public static void main(String[] args) { User axin = new User(); User.School school = new User.School(); axin.setName("hello"); String value1 = optionAlBean.ofNullable (axin).getBean(User::getSchool) .getBean(User.School::getAdress).get(); System.out.println(value1); Boolean present = optionalbean.ofNullable (axin).getBean(User::getSchool) .getBean(User.School::getAdress).isPresent(); System.out.println(present); Optionalbean.ofnullable (axin).getBean(User::getSchool).getBean(user.school :: getress) .ifpresent (adress -> system.out.println (string.format (" address exists :%s", adress))); OrElse String value2 = optionAlBean.ofNullable (axin).getBean(User::getSchool) .getbean (user.school ::getAdress).orelse (" home "); System.out.println(value2); OrElseThrow try {String value3 = optionAlBean.ofNullable (axin).getBean(User::getSchool) .getBean(user.school ::getAdress).orelsethrow (() -> new RuntimeException(" null pointer ")); } catch (Exception e) { System.out.println(e.getMessage()); }}Copy the code

Run:

conclusion

Designed a tool that can chain call object members without nulling to make the code more accurate and elegant, if the tool designed in this paper meets just solve your problems, then use it in the project!

If you have more design or the article has the error, also please leave a message to discuss together, mutual progress!