Java - NPE(NullPointerException);Optional

一、NPE(NullPointerException)

NPE(java.lang.NullPointerException) : Null pointer exception

(1) Scenarios where NPE is prone to occur

1. The return type is a basic data type. When the return package data type object is automatically unboxed, NPE may occur.

2. The query result of the database may be null.

3. Even if the elements in the collection are isNotEmpty, the data elements taken out may be null.

4. When remote calls return objects, null pointer judgment is always required to prevent NPE.

5. For the data obtained in the Session, it is recommended to perform NPE checks to avoid null pointers.

6. Cascading calls to obj.getA().getB().getC(); a series of calls can easily cause NPE

(2) How to reduce the occurrence of NPE

1. Comply with code specifications

A good coding standard can reduce the occurrence of errors to a certain extent. It is recommended to read Alibaba’s Java Development Manual. It has been updated to the Taishan version. You can download it directly from the official website.

2. Use the Optional class

Use the new feature Optional class introduced in JDK8 to prevent NPE problems, because the main problem solved by the Optional class is NPE

3. Null value detection

Use if(obj == null) to detect the object we need to detect. When Null is detected, a targeted exception type can be thrown

2. Java 8 Optional class

A very interesting feature introduced in Java 8 is  the Optional   class. The main problem that the Optional class solves is the infamous NullPointerException - an exception that every Java programmer knows very well.

Essentially, this is a wrapper class that contains optional values, which means that the Optional class can contain objects or be empty.

Optional is a strong step toward functional programming in Java and helps implement it within the paradigm. But the meaning of Optional is obviously more than that

The following is quoted from the novice tutorial

Java 8 Optional Class | Newbie Tutorial

The Optional class is a container object that can be null. If the value exists, the isPresent() method will return true, and calling the get() method will return the object.

Optional is a container: it can hold a value of type T, or just null. Optional provides many useful methods so that we don't have to explicitly detect null values.

The introduction of the Optional class solves the null pointer exception very well.

class declaration

The following is a  declaration of the java.util.Optional<T>  class:

public final class Optional<T> extends Object

class method

serial number Method & Description
1 static <T> Optional<T> empty()

Returns an empty Optional instance.

2 boolean equals(Object obj)

Determine whether other objects are equal to Optional.

3 Optional<T> filter(Predicate<? super <T> predicate)

If the value exists and the value matches the given predicate, an Optional describing the value is returned, otherwise an empty Optional is returned.

4 <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

If the value exists, returns the value based on the mapping method contained in the Optional, otherwise returns an empty Optional

5 T get()

If this value is contained in this Optional, the value is returned, otherwise an exception is thrown: NoSuchElementException

6 int hashCode()

Returns the hash code of the existing value, or 0 if the value does not exist.

7 void ifPresent(Consumer<? super T> consumer)

If the value exists, call the consumer with the value, otherwise do nothing.

8 boolean isPresent()

The method returns true if the value exists, false otherwise.

9 <U>Optional<U> map(Function<? super T,? extends U> mapper)

If there is a value, call the mapping function on it to get the return value. If the return value is not null, create an Optional containing the map return value as the map method return value, otherwise an empty Optional is returned.

10 static <T> Optional<T> of(T value)

Returns an Optional specifying a non-null value.

11 static <T> Optional<T> ofNullable(T value)

If it is non-null, returns the specified value described by Optional, otherwise returns an empty Optional.

12 T orElse(T other)

If the value exists, return the value, otherwise return other.

13 T orElseGet(Supplier<? extends T> other)

If the value exists, return the value, otherwise trigger other and return the result of other call.

14 <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

If the value exists, return the contained value, otherwise throw an exception inherited by Supplier

15 String toString()

Returns an Optional non-empty string for debugging

注意: 这些方法是从 java.lang.Object 类继承来的

Optional 实例

我们可以通过以下实例来更好的了解 Optional 类的使用:

Java8Tester.java 文件

import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允许传递为 null 参数
      Optional<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      // Optional.isPresent - 判断值是否存在
        
      System.out.println("第一个参数值存在: " + a.isPresent());
      System.out.println("第二个参数值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,返回它,否则返回默认值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 获取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}

执行以上脚本,输出结果为:

$ javac Java8Tester.java 
$ java Java8Tester 
第一个参数值存在: false 
第二个参数值存在: 
true 10

工作中经常会遇到,查询返回空,如果没有判空处理,一不小心就会空指针异常。

从一个简单的用例开始。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

在这个小示例中,如果我们需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查:

    if(user !=null){
        Address address = user.getAddress();
        if (address != null) {
            Country country = address.getCountry();
            if (country != null) {
                String isocode = country.getIsocode();
                if (isocode != null) {
                    isocode = isocode.toUpperCase();
                }
            }
        }
    }

你看到了,这很容易就变得冗长,难以维护

加上 if 判断处理也可以,但是会导致代码变得异常冗余,Java8有更优雅的处理方式

public static void main(String[] args) {
        List<String> list = null;
        List<String> newList = Optional.ofNullable(list).orElse(Lists.newArrayList());
        newList.forEach(x -> System.out.println(x));
    }

先解释代码含义:如果list集合不为空,将list集合赋值给newList;如果list集合为空创建一个空对象集合赋值给newList,保证list集合永远不为空,也就避免了空指针异常。(为了更好的理解,分开写了,比较庸俗,实际工作中都是一行搞定,哈哈哈)

再看看源码:底层是怎么处理的,怎么就避免了空指针呢?

//静态变量 empty
private static final Optional<?> EMPTY = new Optional<>();
 
//如果对象为空,执行empty()方法;不为空,执行of(value)方法
public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
 
public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
 
public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

1、首先执行ofNullable()方法,如果T对象为空,执行empty()方法;不为空,执行of(value)方法

2、empty()方法,初始化一个空对象Optional(空对象和null不是一回事)

3、of(value)方法,将泛型对象T用于Optional构造方法的参数上,返回一个有值的对象

4. After the above two steps, it is ensured that Optional is not null and avoids null pointers.

JAVA 8/9 -- Understanding, learning and using Optional in Java (mainly solving the null pointer NPE problem)_jiwei_style's blog-CSDN blog

Guess you like

Origin blog.csdn.net/MinggeQingchun/article/details/130796263