荐 java中如何优雅的进行null值处理

2022-08-02,,

一、空指针

 NPE(NullPointerException)一直是让java程序员头疼的问题,稍微不注意被调用就会让功能无法使用。所以项目里面很多地方都需要对对象进行非空判断。

二、非空处理

 那么我们通常是怎样的判空的呢?

if (obj == null) {
	// do something
} else {
	// do something
}

 这段代码是不是很常见?如果obj为null,那么就执行一段逻辑,否则执行另外一段逻辑。
 由于这样的逻辑会占用很多代码行,也会让代码看起来变得臃肿,所以java官方在java8中优化了相关的链式处理,比如java8中的stream流,而在这里,也有对应的Optional类来处理判空问题。
首先来解读一下Optional类:

package java.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public final class Optional<T> {
   // 空的Optional对象
    private static final Optional<?> EMPTY = new Optional<>();

    // 如果非空,就是value值,如果为空,就没有值
    private final T value;

	// 无参构造,将value初始化为null
    private Optional() {
        this.value = null;
    }

   // 获取一个Optional对象,value为null
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

   // 使用构造器生成一个Optional对象,如果value值为null,就抛出空指针异常
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

	// 使用静态方法获取一个Optional对象,如果value值为null,就抛出空指针异常
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

  	// 如果value为null,返回value为null的Optional对象,否则生成一个value为传入value的对象
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    // 获取当前Optional对象的value值,如果value为null,则抛出异常
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    // 判断当前Optional对象value值是否非空,不为null则返回true
    public boolean isPresent() {
        return value != null;
    }

    // 对当前Optional对象的value值进行操作
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
        	// 使用consumer消费者方法
            consumer.accept(value);
        // 否则不做任何操作
    }

    // 根据条件过滤Optional对象
    public Optional<T> filter(Predicate<? super T> predicate) {
    	 // 如果predicate比较方法为null,则抛出空指针异常
        Objects.requireNonNull(predicate);
       	// 如果value值为空,则返回当前Optional对象
        if (!isPresent())
            return this;
        else
        	// 如果value有值
        	// 则使用predicate进行比较,如果匹配则返回当前Optional对象
        	// 不匹配则返回一个value为null的Optional对象
            return predicate.test(value) ? this : empty();
    }

	// 将当前Optional对象的value根据mapper函数封装成另外的Optional对象
	// mapper函数入参的类型为value类型的超类型,返回类型为U类型的子类型
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
     	// 如果mapper函数为null,则抛出空指针异常
        Objects.requireNonNull(mapper);
        // 如果value值为空,则返回value为null的Optional对象
        if (!isPresent())
            return empty();
        else {
        	// 如果value有值
        	// 将mapper.apply(value)的返回值等装成一个Optional对象
            return Optional.ofNullable(mapper.apply(value));
        }
    }

  	// 将当前Optional对象的value根据mapper函数封装成另外的Optional对象
	// mapper函数入参的类型为value类型的超类型,返回类型为value为U类型的Optional对象
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    	// 如果mapper函数为null,则抛出空指针异常
        Objects.requireNonNull(mapper);
        // 如果value值为空,则返回value为null的Optional对象
        if (!isPresent())
            return empty();
        else {
        	// 如果value有值
        	// 如果mapper.apply(value)为null,则抛出空指针异常
        	// 返回mapper.apply(value)
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

    // 如果value不为空则返回value,否则返回other
    public T orElse(T other) {
        return value != null ? value : other;
    }

    // 如果value不为空则返回value,否则返回other.get()
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    // 如果value不为空则返回value,否则抛出exceptionSupplier.get()定义的异常
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

   	// 比较当前Optional对象与obj是否相等
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Optional)) {
            return false;
        }

        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }

    // 获取当前value的hashcode
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    // toString
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

 通过解读源代码,相信大家对Optional类有了一定的了解了吧!
 那么我们来举几个实例,加深一下印象。
 新建一个User实体,来进行测试:

package com.yl.test;

/**
 * 用户实体
 *
 * @author hanguilin
 * @date 2020年7月16日 下午1:32:36
 * @version 1.0
 * 
 */
public class User {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

	public User() {
        super();
    }
    
    public User(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

  1. 如果user实例不为空,则打印年龄
package com.yl.test;

import java.util.Optional;

public class TestMain {

    public static void main(String[] args) {
        User user = null;
        Optional<User> userOptional = Optional.ofNullable(user);
        userOptional.ifPresent(o -> System.out.println(o.getAge()));
    }
}

 此时控制台没有任何输出。
 我们来测试一下user有值的情况:

User user = new User("han", 20);

此时:

 如果想将链式写法运用足,那么上面就可以缩写成:

Optional.ofNullable(user).ifPresent(o -> System.out.println(o.getAge()));
  1. 如果user实例不为空,则获取年龄,如果为空,新建一个实例,并获取年龄,此时获取的年龄为null
package com.yl.test;

import java.util.Optional;

public class TestMain {

    public static void main(String[] args) {
        User user = new User("han", 20);
        Integer age = Optional.ofNullable(user).orElse(new User()).getAge();
        System.out.println(age);
    }
}

  1. 如果user实例不为空,则获取年龄,如果为空,返回年龄为0
package com.yl.test;

import java.util.Optional;

public class TestMain {

    public static void main(String[] args) {
        User user = null;
        Optional<Integer> map = Optional.ofNullable(user).map(User::getAge);
        Integer age = map.orElse(0);
        System.out.println(age);
    }
}
  1. 判断对象是否有值
package com.yl.test;

import java.util.Optional;

public class TestMain {

    public static void main(String[] args) {
        User user = null;
        boolean present = Optional.ofNullable(user).isPresent();
        System.out.println(present);
    }
}

本文地址:https://blog.csdn.net/qq_37171817/article/details/107242502

《荐 java中如何优雅的进行null值处理.doc》

下载本文的Word格式文档,以方便收藏与打印。