一、空指针
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;
}
}
- 如果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()));
- 如果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);
}
}
- 如果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);
}
}
- 判断对象是否有值
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);
}
}