对象为null的几种判断方法

NullPointerException出现原因:

如果一个对象为空,但是此时我们调用它的方法,就会遇到NullPointerException问题

我们定义Passenger、Address类

class Passenger{
    private String name;
    private String phone;
    private Address address;
}
class Address{
    private String province;
    private String city;

然后执行如下方法:

public static void main(String[] args) {
        Passenger passenger = new Passenger();
        passenger.getAddress().getCity();
    }

很显然,此时,我们没有给address赋值,却调用它的方法,会抛出 NullPointerException

Exception in thread "main" java.lang.NullPointerException
at com.study.nulljudge.Test.main(Test.java:7)

平时,我们会这样进行 NullPointerException异常的避免:

if (passenger.getAddress() != null){
    passenger.getAddress().getCity();
}

或者:

if (null != passenger.getAddress()) {
    passenger.getAddress().getCity();
}

至于上面的null是写在==前面,还是后面,对于Java语言来说是没有什么区别的,但是Java规范建议null写在==前面。

而对于其它语言,例如C语言,由于C允许if(v1=null)这种判断,其实这里漏写个=号,但是程序不会报错,会导致一些问题。因此C语言为了避免漏写=,因此要求null写在==号前面,即if(null==v1),这样即使漏写=号,即写成if(null=v1),编译器就会编译不通过,通知程序员代码有误,可以及时更改。

上述已经可以处理对象为空的情况,通过if(null != passenger.getAddress()){…},但是这种写法不够优雅,Java8提供Optional类要优化这种写法,具体如下:

一、获取Optional对象的方法

1.Optional构造方法

public final class Optional<T> {
private Optional() {
    this.value = null;
    }
private Optional(T value) {
    this.value = Objects.requireNonNull(value);
    }
}

可以看到,Optional被final所修饰,该类不允许被继承,并且构造方法修饰符private,不允许外部通过构造方法获取Optional实例。

Objects.requireNonNull(value)方法中value值为空,也会报NullPointerException

2.of(T vlaue)方法

那么如何获取Optional实例呢,通过调用of方法

public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}
  • 可以看到of方法内部调用Optional有参构造方法,而Optional有参构造方法上面也讲了,如果传入的value为null,依旧会报NullPointerException
  • 如果传入的value值不为空,会正常构造Optional对象

3.empty()方法

private static final Optional<?> EMPTY = new Optional<>();
private Optional() {this.value = null;}
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

empty方法也会返回一个Optional类型的对象EMPTY,但是对象的值为null

4.ofNullable(T value)

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}
  • 当传递进来的value为null时,返回一个EMPTY对象
  • 当传递进来的value不为null,调用of方法构造对象

和普通of方法的区别在于:当value为空,ofNullable方法不报错,返回一个EMPTY对象,但是of方法报错

5.orElse,orElseGet,orElseThrow

public T orElse(T other) {
    return value != null ? value : other;
}
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

可以看到,orElse,orElseGet,orElseThrow当value为空时有效果

6.map(Function<? super T, ? extends U> mapper)

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

这个函数的作用就是转换值的操作,例如:

String phone = Optional.ofNullable(passenger).map(p -> p.getPhone()).get();

**7.**flatMap(Function<? super T, Optional> mapper)

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}

如果Passenger的getPhone方法变为这样:

class Passenger{
    private String name;
    private String phone;
    private Address address;

    public Optional<String> getPhone(){
        return Optional.ofNullable(phone);
    }
}

此时可以使用flatMap进行值的转换

String phone = Optional.ofNullable(passenger).flatMap(p -> p.getPhone()).get();

8.isPresent()

isPresent()判断当前值是否为空

public boolean isPresent() {
    return value != null;
}

9.ifPresent(Consumer<? super T> consumer)

ifPresent就是在当前值不为空的情况下做一些操作

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

例如:

Optional.ofNullable(passenger).ifPresent(p -> {
    //做一些其它操作
});

10.filter(Predicate<? super T> predicate)

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

接受一个过滤条件,如果条件满足,返回原Optional对象,否则返回EMPTY对象

例如:

Optional.ofNullable(passenger).filter(p -> p.getPhone().length() == 12);

好了,上述就是Optional的具体用法了,那么如何替换掉 if(p != null)呢?

用法如下:

旧写法:

    public String getProvince(Passenger p){
        if (p != null) {
            Address address = p.getAddress();
            if (address != null) {
                String province = address.getProvince();
                if (province != null) {
                    return province;
                }
            }
        }
        throw new NullPointerException("无法找到!!!");
    }

新写法:

public String getProvince(Passenger p){
    return Optional.ofNullable(p)
            .map(p -> p.getAddress())
            .map(address -> address.getProvince())
            .orElseThrow(() -> new NullPointerException("无法找到!!!"));
}

虽然使用链式表达式,代码看起来更优雅了,但是可读性降低了,大家可以根据需要自行选择哪种判空方式。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值