一文教你掌握Java如何实现判空

 更新时间:2023年04月21日 09:00:42   作者:LoneWalker  
实际项目中我们会有很多地方需要判空校验,如果不做判空校验则可能产生NullPointerException异常。所以本文小编为大家整理了Java中几个常见的判空方法,希望对大家有所帮助

1、前言

实际项目中我们会有很多地方需要判空校验,如果不做判空校验则可能产生NullPointerException异常。

针对异常的处理我们在上一篇有提及:

先来看一下实际项目中一些判空方式

if (ObjectUtil.isNotNull(vo.getSubmitterId())) {
    userIds.add(vo.getSubmitterId());
}
if (StringUtils.isNotBlank(vo.getBudgetPM())) {
    userIds.add(Long.valueOf(vo.getBudgetPM()));
}
if (CollUtil.isNotEmpty(vo.getOriginatorList())) {
    userIds.addAl1(vo.getOriginatorList().stream();
}

通常我们判断一个对象是否为Null,可以使用java.util中的Objects.nonNull(obj)、hutool中的ObjectUtil或者直接 null != obj

2、List的判空

像List这种比较特殊的在项目中可能不仅仅是判断非空了。对于List来说不等于null和List.size()不等于0是两回事,公司也有实习生常常有把这两个混淆的情况,list不等于null说明已经初始化了,堆内存中有一块属于它的地盘,而size为0说明还没往里面放东西,举个例子说就是不等于null代表我现在有个瓶子,size大于0说明我向瓶子里装水了。

实际项目中也发现有直接用list.isEmpty()去判断的,来看一下源码:

public boolean isEmpty() {
    return size == 0;
}

相当于判断瓶子里有没有水(前提是瓶子已经存在,若瓶子不存在,则会抛出NullPointerException异常)。

所以通常情况下会连用list != null && list.size > 0 来判断,或者直接使用HuTool中CollUtil工具的isEmpty。诸如此类的还有Set、Map等

3、String的判空

这里还是用瓶子与水的概念,String为null时调用equals(String) 或 length() 等操作抛出 java.lang.NullPointerException。

针对字符串判空有以下几种方式:

1、大多数人使用的方法之一,直观,方便,但效率低下:

if(a == null || a.equals(""));

2、比较字符串长度,高效:

if(a == null || a.length() == 0);

3、Java SE 6.0 才刚刚开始提供,效率和方法二差不多:

if(a == null || a.isEmpty());

当然还可以使用org.apache.commons.lang.StringUtils工具。

StringUtils.isNotBlank(a);

* StringUtils.isNotBlank(null) = false

* StringUtils.isNotBlank("") = false

* StringUtils.isNotBlank(" ") = false

* StringUtils.isNotBlank("bob") = true

* StringUtils.isNotBlank(" bob ") = true

该工具类中还有个isNotEmpty()方法,从注释可以很明显看出二者的差别

StringUtils.isNotEmpty(a);

* StringUtils.isNotEmpty(null) = false

* StringUtils.isNotEmpty("") = false

* StringUtils.isNotEmpty(" ") = true

* StringUtils.isNotEmpty("bob") = true

* StringUtils.isNotEmpty(" bob ") = true

4、Optional

Optional的出现就是用来防止NullpointException的。常见的方法有:

  • .empty():创建一个空的Optional实例
  • .of(T t) : 创建一个Optional 实例,为null时报异常
  • .ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
  • isPresent() : 判断容器中是否有值
  • ifPresent(Consume lambda) :容器若不为空则执行括号中的Lambda表达式
  • orElse(T t) : 获取容器中的元素,若容器为空则返回括号中的默认值
  • orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
  • orElseThrow() :如果为空,就抛出定义的异常,如果不为空返回当前对象
  • map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
  • flatMap(Function mapper):与map 类似,要求返回值必须是Optional
  • T get() :获取容器中的元素,若容器为空则抛出NoSuchElement异常

先看个常见的示例:

baseInfo类中有布尔类型的属性,是空返回false,不为空取其值,需要四行。

boolean blind = false;
if (null != baseInfo.getBlind()){
    blind = baseInfo.getBlind();
}

当使用Optional时,一行搞定,非常的优雅。

boolean blind = Optional.ofNullable(baseInfo.getBlind()).orElse( other: false);

4.1 Optional对象的创建

public final class Optional<T> {
    private static final Optional<?> EMPTY = new Optional<>();
    private final T value;
    //可以看到两个构造方格都是private 私有的
    //说明 没办法在外面new出来Optional对象
    private Optional() {
        this.value = null;
    }
    private Optional(T value) {
        this.value = Objects.requireNonNull(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);
    }
    //这个静态方法大致是 如果参数value为空,则创建空对象,如果不为空,则创建有参对象
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
}

4.2使用场景

场景1:在service层中 查询一个对象,返回之后判断是否为空并做处理

Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Optional.ofNullable(task).orElseThrow(() -> new ProcessException(ErrorCodeEnum,SYSIEM ERROR));

场景2:使用Optional 和函数式编程,一行搞定

Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String,String> map = new HashMap<>( initialCapacity: 8);
Optional.ofNullable(task).ifPresent(d -> map.put("taskId",d.getTaskDefinitionKey()));

5、总结

每种方法的存在必然有适用的场景,有些情况下这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

以上就是一文教你掌握Java如何实现判空的详细内容,更多关于Java判空的资料请关注脚本之家其它相关文章!

相关文章

  • java-servlet-转发AND路径(详解)

    java-servlet-转发AND路径(详解)

    下面小编就为大家带来一篇java-servlet-转发AND路径(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java实现图书借阅系统

    Java实现图书借阅系统

    这篇文章主要为大家详细介绍了Java实现图书借阅系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • JVM Client和Server端有什么区别

    JVM Client和Server端有什么区别

    这篇文章主要介绍了JVM Client和Server端有什么区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • SpringBoot整合Druid实现SQL监控和数据库密码加密

    SpringBoot整合Druid实现SQL监控和数据库密码加密

    Druid连接池是阿里巴巴开源的数据库连接池项目,Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能,本文给大家介绍了SpringBoot整合Druid实现SQL监控和数据库密码加密,文中有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-06-06
  • JavaSE经典小练习项目之拷贝文件夹

    JavaSE经典小练习项目之拷贝文件夹

    文件拷贝是一个常见的任务,无论是备份文件,还是将文件从一个位置复制到另一个位置,文件拷贝都是必不可少的,这篇文章主要给大家介绍了关于JavaSE经典小练习项目之拷贝文件夹的相关资料,需要的朋友可以参考下
    2023-10-10
  • JAVA堆排序算法的讲解

    JAVA堆排序算法的讲解

    这篇文章主要介绍了JAVA堆排序算法的知识点,文中代码非常详细,配合上图片讲解,帮助大家更好的参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 关于activemq安装配置以及启动错误的解决

    关于activemq安装配置以及启动错误的解决

    这篇文章主要介绍了关于activemq安装配置以及启动错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Java中用Socket实现HTTP文件上传实例

    Java中用Socket实现HTTP文件上传实例

    本篇文章主要介绍了Java中用Socket实现HTTP文件上传实例,详细的介绍了通过读取Socket的输入流来实现一个文件上传的功能,有兴趣的同学可以一起了解一下
    2017-04-04
  • Java对象数组的添加、删除和遍历代码示例

    Java对象数组的添加、删除和遍历代码示例

    在Java编程中,我们经常需要对数据结构进行遍历操作,并根据业务需求删除部分元素,这篇文章主要给大家介绍了关于Java对象数组的添加、删除和遍历的相关资料,需要的朋友可以参考下
    2024-04-04
  • SpringBoot自动初始化数据库的方法分享

    SpringBoot自动初始化数据库的方法分享

    我们在项目中应该经常遇到过初始化数据的场景,特别是项目部署或者交付的时候,那么有什么方式可以在项目启动的时候自动初始化数据库呢,下面小编就来和大家分享几个方法吧
    2023-08-08

最新评论