Home  >  Article  >  Java  >  How to avoid null pointer exception in Java

How to avoid null pointer exception in Java

高洛峰
高洛峰Original
2017-01-18 14:42:311642browse

No one likes null pointer exception! 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. A newly introduced type 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 is a better alternative for handling null values ​​(warning: it may not be so obvious at first glance)

Basic Usage

It is a type (a class ) - So, how can you create an instance of this type?

Just use its three static methods:

public static Optional<String> stringOptional(String input) {
    return Optional.of(input);
}

Simple and clear - create an Optional containing this value wrapper. Remember - if this value is null, it will throw NPE!

public static Optional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
input = null;
}
return Optional.ofNullable(input);
}

I personally think it is better. In this way, there will be no risk of NPE - if the input is null, an empty Optional

public static Optional<String> emptyOptional() {
return Optional.empty();
}

will be returned if you really want to return an "empty" value. An "empty" value does not mean null.

Okay, then how to consume/use Optional?

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 benefit this has compared to using if(myObj != null). Don't worry, I'll explain this clearly.

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.

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).

In any case, the obvious difference between these two methods lies in their parameters - you can choose to use lambda expressions instead of instances of Supplier to complete 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 positioning. 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!

Look at this code snippet

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 may be empty?

1.Map object
2.The key used for searching
3.The instance of the method call

If an NPE is thrown, how can we determine which one it is? null?

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 information you see will clearly see the method call of Objects.requireNonNull. 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, for example, implement a simple validator to ensure that there are no null values.

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!

For more related articles on methods to avoid null pointer exceptions in Java, please pay attention to the PHP Chinese website!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn