Java不要再使用!=null判空了!

前言

对于Java程序员来说,null是令人头痛的东西。时常会受到空指针异常(NPE)的骚扰。连Java的发明者都承认这是他的一项巨大失误。

那么,有什么办法可以避免在代码中写大量的判空语句呢?

有人说可以使用 JDK8提供的 Optional 来避免判空,但是用起来还是有些麻烦。

作者在日常工作中,封装了一个工具,可以可以链式调用对象成员而无需判空,相比原有的if null逻辑 和 JDK8提供的 Optional 更加优雅易用,在工程实践中大大提高了编码效率,也让代码更加的精准和优雅。

不优雅的判空调用

我想从事Java开发的小伙伴肯定有遇到过下面这种让人难受的判空逻辑:现在有一个User类,School 是它的成员变量

/**

* @author Axin

* @since 2020-09-20

* @summary 一个User类定义

 * (Ps:Data 是lombok组件提供的注解,简化了get set等等的约定代码)

*/

@Data

public class User {

 private String name;

 private String gender;

 private School school;

 @Data

 public static class School {

  private String scName;

  private String adress;

 }

}

现在想要获得School的成员变量 adress , 一般的处理方式:

public static void main(String[] args) {

 User axin = new User();

 User.School school = new User.School();

 axin.setName("hello");

 if (Objects.nonNull(axin) && Objects.nonNull(axin.getSchool())) {

  User.School userSc = axin.getSchool();

  System.out.println(userSc.getAdress());

 }

}

获取adress时要对School进行判空,虽然有些麻烦,到也能用,通过 JDK8 提供的 Optional 工具也是可以,但还是有些麻烦。
而下文的 OptionalBean 提供一种可以链式不断地调用成员变量而无需判空的方法,直接链式调用到你想要获取的目标变量,而无需担心空指针的问题。

链式调用成员变量

如果用了本文设计的工具 OptionalBean ,那么上述的调用可以简化成这样:

public static void main(String[] args) {

 User axin = new User();

 User.School school = new User.School();

 axin.setName("hello");

 // 1. 基本调用

 String value1 = OptionalBean.ofNullable(axin)

   .getBean(User::getSchool)

   .getBean(User.School::getAdress).get();

 System.out.println(value1);

}

执行结果:

其中User的school变量为空,可以看到代码并没有空指针,而是返回了null。这个工具怎么实现的呢?

OptionalBean 工具

/**

* @author Axin

* @since 2020-09-10

* @summary 链式调用 bean 中 value 的方法

*/

public final class OptionalBean<T> {

 private static final OptionalBean<?> EMPTY = new OptionalBean<>();

 private final T value;

 private OptionalBean() {

  this.value = null;

 }

 /**

  * 空值会抛出空指针

  * @param value

  */

 private OptionalBean(T value) {

  this.value = Objects.requireNonNull(value);

 }

 /**

  * 包装一个不能为空的 bean

  * @param value

  * @param <T>

  * @return

  */

 public static <T> OptionalBean<T> of(T value) {

  return new OptionalBean<>(value);

 }

 /**

  * 包装一个可能为空的 bean

  * @param value

  * @param <T>

  * @return

  */

 public static <T> OptionalBean<T> ofNullable(T value) {

  return value == null ? empty() : of(value);

 }

 /**

  * 取出具体的值

  * @param fn

  * @param <R>

  * @return

  */

 public T get() {

  return Objects.isNull(value) ? null : value;

 }

 /**

  * 取出一个可能为空的对象

  * @param fn

  * @param <R>

  * @return

  */

 public <R> OptionalBean<R> getBean(Function<? super T, ? extends R> fn) {

  return Objects.isNull(value) ? OptionalBean.empty() : OptionalBean.ofNullable(fn.apply(value));

 }

 /**

  * 如果目标值为空 获取一个默认值

  * @param other

  * @return

  */

 public T orElse(T other) {

  return value != null ? value : other;

 }

 /**

  * 如果目标值为空 通过lambda表达式获取一个值

  * @param other

  * @return

  */

 public T orElseGet(Supplier<? extends T> other) {

  return value != null ? value : other.get();

 }

 /**

  * 如果目标值为空 抛出一个异常

  * @param exceptionSupplier

  * @param <X>

  * @return

  * @throws X

  */

 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {

  if (value != null) {

   return value;

  } else {

   throw exceptionSupplier.get();

  }

 }

 public boolean isPresent() {

  return value != null;

 }

 public void ifPresent(Consumer<? super T> consumer) {

  if (value != null)

   consumer.accept(value);

 }

 @Override

 public int hashCode() {

  return Objects.hashCode(value);

 }

 /**

  * 空值常量

  * @param <T>

  * @return

  */

 public static<T> OptionalBean<T> empty() {

  @SuppressWarnings("unchecked")

  OptionalBean<T> none = (OptionalBean<T>) EMPTY;

  return none;

 }

}

工具设计主要参考了 Optional 的实现,再加上对链式调用的扩展就是上述的OptionalBean。
getBean 其实是当变量为空时返回了一个 包装空值的 OptionalBean 对象,同时泛型的使用让工具更加易用。

使用手册

可以看到代码中也提供了和 Optional 一样的扩展方法,如 ifPresent()、orElse()等等:

public static void main(String[] args) {

 User axin = new User();

 User.School school = new User.School();

 axin.setName("hello");

 // 1. 基本调用

 String value1 = OptionalBean.ofNullable(axin)

   .getBean(User::getSchool)

   .getBean(User.School::getAdress).get();

 System.out.println(value1);

 // 2. 扩展的 isPresent方法 用法与 Optional 一样

 boolean present = OptionalBean.ofNullable(axin)

   .getBean(User::getSchool)

   .getBean(User.School::getAdress).isPresent();

 System.out.println(present);

 // 3. 扩展的 ifPresent 方法

 OptionalBean.ofNullable(axin)

   .getBean(User::getSchool)

   .getBean(User.School::getAdress)

   .ifPresent(adress -> System.out.println(String.format("地址存在:%s", adress)));

 // 4. 扩展的 orElse

 String value2 = OptionalBean.ofNullable(axin)

   .getBean(User::getSchool)

   .getBean(User.School::getAdress).orElse("家里蹲");

 System.out.println(value2);

 // 5. 扩展的 orElseThrow

 try {

  String value3 = OptionalBean.ofNullable(axin)

    .getBean(User::getSchool)

    .getBean(User.School::getAdress).orElseThrow(() -> new RuntimeException("空指针了"));

 } catch (Exception e) {

  System.out.println(e.getMessage());

 }

}

run一下:

总结

设计了一种可以链式调用对象成员而无需判空的工具让代码更加的精准和优雅,如果本文设计的工具满足了刚好解决你的困扰,那就在项目中使用吧!

到此这篇关于Java不要再使用!=null判空的文章就介绍到这了,更多相关Java不使用!=null判空内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java代码中如何去掉烦人的“!=null”

    问题 为了避免空指针调用,我们经常会看到这样的语句 ...if (someobject != null) { someobject.doCalc();}... 最终,项目中会存在大量判空代码,多么丑陋繁冗!如何避免这种情况?我们是否滥用了判空呢? 精华回答: 这是初.中级程序猿经常会遇到的问题.他们总喜欢在方法中返回null,因此,在调用这些方法时,也不得不去判空.另外,也许受此习惯影响,他们总潜意识地认为,所有的返回都是不可信任的,为了保护自己程序,就加了大量的判空. 吐槽完毕,回到这个题目本

  • 还在用if(obj!=null)做非空判断,带你快速上手Optional

    1.前言 相信不少小伙伴已经被java的NPE(Null Pointer Exception)所谓的空指针异常搞的头昏脑涨, 有大佬说过"防止 NPE,是程序员的基本修养."但是修养归修养,也是我们程序员最头疼的问题之一,那么我们今天就要尽可能的利用Java8的新特性 Optional来尽量简化代码同时高效处理NPE(Null Pointer Exception 空指针异常) 2.认识Optional并使用 简单来说,Opitonal类就是Java提供的为了解决大家平时判断对象是否为空

  • Java不要再使用!=null判空了!

    前言 对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误. 那么,有什么办法可以避免在代码中写大量的判空语句呢? 有人说可以使用 JDK8提供的 Optional 来避免判空,但是用起来还是有些麻烦. 作者在日常工作中,封装了一个工具,可以可以链式调用对象成员而无需判空,相比原有的if null逻辑 和 JDK8提供的 Optional 更加优雅易用,在工程实践中大大提高了编码效率,也让代码更加的精准和优雅. 不优

  • java json不生成null或者空字符串属性(详解)

    大家平时用java对象转json字符串.null或者空字符串属性是不需要生成到json字符串里面的. 如下方式生成,没有使用的属性也会生成json字符串属性. JSONArray jsonarray = JSONArray.fromObject(ecmMessageMap.values()); msgObj = jsonarray.toString(); {"actionType":"","clientIp":"","

  • java返回集合为null还是空集合及空集合的三种写法小结

    目录 返回集合为null还是空集合及空集合的三种写法 返回空List的方式 方式一:new ArrayList()   方式二:new ArrayList(0) 方式三:Collections.emptyList()(推荐) 返回集合为null还是空集合及空集合的三种写法 个人认为在自己写接口时,需要返回集合时返回一个空集合,比如mybatis查询如果返回一个集合,结果为空时也会返回一个空集合而不是null. 那么这样有什么好处呢?最大的好处就是调用方不用在判断是否为null,可以直接用,因为不

  • 如何在Java中优雅地判空详解

    前言 整天都是在跟Java打交道.我在Java开发中最常用的一段代码就是用object != null在使用对象之前判断是否为空.这么做是为了避免NullPointerException.但是我发现这样检测代码实在是太丑了,而且及其不可读. 那有没有一种优雅的替代方法呢? 判空灾难 作为搬砖党的一族们,我们对判空一定再熟悉不过了,不要跟我说你很少进行判空,除非你喜欢NullPointerException. 不过NullPointerException对于很多猿们来说,也是Exception家族

  • Java如何使用Optional与Stream取代if判空逻辑(JDK8以上)

    通过本文你可以用非常简短的代码替代业务逻辑中的判null校验,并且很容易的在出现空指针的时候进行打日志或其他操作. 注:如果对Java8新特性中的lambda表达式与Stream不熟悉的可以去补一下基础,了解概念. 首先下面代码中的List放入了很多Person对象,其中有的对象是null的,如果不加校验调用Person的getXXX()方法肯定会报空指针错误,一般我们采取的方案就是加上if判断: public class DemoUtils { public static void main(

  • Java Optional的判空操作详解

    目录 Optional判空 代码模拟 Optional常用方法 使用Optional一定比null好吗 Optional 使用场景 Optional判空 JAVA在1.8版本推出Optional,官方文档将其描述为可能包含或不包含非空值的容器对象,目前Optional用于避免程序出现异常NullPointerException. 代码模拟 // 下面所有类省略set,get方法 public class Employee { private String employeeName; privat

  • 一文教你搞定Java Optional类判空操作

    目录 概述 创建Optional实例 获取Optional中的值 判断Optional是否为空 Optional中的过滤.转换方法 概述 最近项目组内做code review,充斥着大量的.原始的.丑陋的判空语句,大致类似下面的代码: if (user != null) { Address address = user.getAddress(); if (address != null) { Country country = address.getCountry(); if (country

  • java poi 读取单元格null或者空字符串方式

    目录 java poi 读取单元格null或空字符串 java poi读取excel单元格为空的数据,出现空指针异常 产生原因 问题解决 java poi 读取单元格null或空字符串 Cell cell = row.getCell(j, Row.RETURN_BLANK_AS_NULL); 需求 :策划同学填写的单元格有时为null 有时为空串 分条件处理 getcell 可以传入指定的策略 根据需求拿到结果分需处理 java poi读取excel单元格为空的数据,出现空指针异常 空指针异常:

  • Java中String判断值为null或空及地址是否相等的问题

    String的null或空值的判断处理 笔者在开发过程中,常常碰到过下面这些错误的用法: 1,错误用法一: if (name == "") { //do something } 2,错误用法二: if (name.equals("")) { //do something } 3,错误用法三: if (!name.equals("")) { //do something } 我们来解说一下: 上述错误用法1是初学者最容易犯,也最不容易被发现的错误,

  • Java8 Optional判空详解(简化判空操作)

    一.导语 在没有用Optional判空之前,你是否也像下面的代码一样判空呢?如果是,请往下看,Optional 相对传统判空的优势. 传统阶层判空 为什么要用Optional,它到底是什么东西 你也看到了上面的那张图,一旦代码量大起来了,条件多了,代码就会变得很冗余,变得难以维护.那么此时我们就有必要了解Optional了. Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象.Optional 是个容器:它可以

随机推荐