No one likes NullPointerException! Is there any way to avoid them? Maybe. .
This article will discuss the following technologies
1.Optional type (newly introduced in Java 8)
2.Objects class (original in Java 7)
Optional class in Java 8
what is it?
1. New types introduced in Java 8
2. It is used as a wrapper for an object of a specified type or for scenarios where no object (null) exists
Simply put, it's a better alternative for handling null values (warning: it may not be so obvious at first glance)
Basic usage
It's a type (a class) - so how do you create an instance of this type?
Just use its three static methods:
Copy the code code as follows:
public static Optional<String> stringOptional(String input) {
return Optional.of(input);
}
Simple and clear - create an Optional wrapper containing this value. Remember - if this value is null, it will throw NPE!
Copy the code code as follows:
public static Optional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
input = null;
}
return Optional.ofNullable(input);
}
I personally think it's better. This way there will be no risk of NPE - if the input is null, an empty Optional will be returned.
Copy the code code as follows:
public static Optional<String> emptyOptional() {
return Optional.empty();
}
If you really just want to return a "null" value. An "empty" value does not mean null.
Okay, so how to consume/use Optional?
Copy the code code as follows:
public static void consumingOptional() {
Optional<String> wrapped = Optional.of("aString");
if (wrapped.isPresent()) {
System.out.println("Got string - " + wrapped.get());
}
else {
System.out.println("Gotcha !");
}
}
The simple way is to check whether the Optional wrapper actually has a value (using the isPresent method) - you will wonder what advantage this has over using if(myObj != null). Don't worry, I'll explain this clearly.
Copy the code code as follows:
public static void consumingNullableOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
You can use the orElse method, so that if the encapsulated value is indeed a null value, you can use it to return a default value - its benefits are obvious. When extracting the real value, you can avoid the obviously redundant method of calling the ifPresent method.
Copy the code code as follows:
public static void consumingEmptyOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
return "defaultBySupplier";
}
));
}
I'm a little confused about this. Why are there two different methods for the same purpose? orElse and orElseGet can obviously be overloaded (with the same name but different parameters).
Anyway, the obvious difference between these two methods is their parameters - you can choose to use lambda expressions instead of instances of Supplier to accomplish this (a functional interface)
Why is using Optional better than the common null check?
1. The biggest advantage of using Optional is that you can express your intention more clearly - returning a null value will make consumers confused (when NPE does occur) whether this is returned intentionally, so you have to check the javadoc for further details. position. Using Optional is quite straightforward.
2. With Optional, you can completely avoid NPE - as mentioned above, using Optional.ofNullable, orElse and orElseGet can keep us away from NPE.
Another savior!
Take a look at this code snippet and copy the code below:
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getVal(Map<String, String> aMap, String key) {
return aMap.containsKey(key) ? aMap.get(key) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getVal(null, "dummy");
}
}
Which one might be empty?
1.Map object
2. Key used for search
3. This instance of method call
If NPE is thrown, how can we determine which one is null?
Copy the code code as follows:
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getValSafe(Map<String, String> aMap, String key) {
Map<String, String> safeMap = Objects.requireNonNull(aMap,
"Map is null");
String safeKey = Objects.requireNonNull(key, "Key is null");
return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getValSafe(null, "dummy");
}
}
requireNonNull method
1. If the object is not null, return itself
2. If the value is null, the returned NPE will have the specified message.
Why is it better than if(myObj!=null)?
The stack trace you see will clearly see the Objects.requireNonNull method call. This, combined with your own error log, can allow you to locate the problem faster. . . At least it's faster in my opinion.
You can also customize your own validator, such as implementing a simple validator to ensure that there are no null values.
Copy the code code as follows:
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
public class RandomGist {
public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
Objects.requireNonNull(object);
Objects.requireNonNull(predicate);
if (predicate.test(object)){
throw new IllegalArgumentException(msgToCaller);
}
return object;
}
public static void main(String[] args) {
//Usage 1: an empty string (intentional)
String s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "My String is Empty!"));
//Usage 2: an empty List (intentional)
List list = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "List is Empty!").size());
//Usage 3: an empty User (intentional)
User user = new User("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "User is Empty!"));
}
private static class User {
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return name;
}
}
}
Don't let NPE become a pain in the wrong place. We have many tools to better deal with NPEs and even eradicate them completely!