求求你,不要再使用!=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等等的约定代码)*/@Datapublic class User {private String name;private String gender;private School school;@Datapublic 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);}@Overridepublic 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. 扩展的 orElseString value2 = OptionalBean.ofNullable(axin).getBean(User::getSchool).getBean(User.School::getAdress).orElse("家里蹲");System.out.println(value2);// 5. 扩展的 orElseThrowtry {String value3 = OptionalBean.ofNullable(axin).getBean(User::getSchool).getBean(User.School::getAdress).orElseThrow(() -> new RuntimeException("空指针了"));} catch (Exception e) {System.out.println(e.getMessage());}}

run一下:

总结

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

如果您有更的设计或者文中有错误,还请留言一起讨论,互相进步!


往期推荐这8种常见的SQL错误用法,你还在用吗?
千万不要这样写代码!9种常见的OOM场景演示
用好MySQL的21个好习惯!
关注我,每天陪你进步一点点!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545170.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统的基本法则

Linux基本法则&#xff1a;1.一切皆文件&#xff1a;Linux系统中基本上都为文件组成&#xff0c;包括配置文件、硬件信息等&#xff1b;2.由重多的单一目的小程序组成&#xff0c;并且将各种小程序组合可以完成复杂任务&#xff1b;3.尽可能避免捕获用户接口&#xff0c;为了方…

android字符串复制到剪贴板

android2.1之后版本 其一&#xff1a;&#xff08;已运行成功 &#xff09;ClipboardManager clip (ClipboardM anager)getSystemService(Context.CLIPB OARD_SERVICE); clip.getText();// 粘贴clip.setText(str); // 复制其二&#xff1a;ClipboardM anager c (ClipboardMana…

date.gethour_Java LocalDateTime类| 带示例的getHour()方法

date.gethourLocalDateTime类getHour()方法 (LocalDateTime Class getHour() method) getHour() method is available in java.time package. getHour()方法在java.time包中可用。 getHour() method is used to get an hour-of-day field value from this date-time object. ge…

JDBC(Java语言连接数据库)

JDBC&#xff08;Java语言连接数据库&#xff09;JDBC本质整体结构基层实现过程&#xff08;即用记事本而不是idea&#xff09;第一种实现方式第二种实现方式乐观锁和悲观锁乐观锁悲观锁JDBC本质 整体结构 基层实现过程&#xff08;即用记事本而不是idea&#xff09; 第一种实…

那些牛逼的数据分析师,SQL用的到底有多溜

从各大招聘网站中可以看到&#xff0c;今年招聘信息少了很多&#xff0c;但数据分析相关岗位有一定增加&#xff0c;而数据分析能力几乎已成为每个岗位的必备技能。是什么原因让企业如此重视“数据人才”&#xff1f;伴随滴滴出行、智慧营销等的落地商用&#xff0c;部分企业尝…

knn机器学习算法_K-最近邻居(KNN)算法| 机器学习

knn机器学习算法Goal: To classify a query point (with 2 features) using training data of 2 classes using KNN. 目标&#xff1a;使用KNN使用2类的训练数据对查询点(具有2个要素)进行分类。 K最近邻居(KNN) (K- Nearest Neighbor (KNN)) KNN is a basic machine learning…

Linux 指令的分类 (man page 可查看)

man page 常用按键 转载于:https://www.cnblogs.com/aoun/p/4324350.html

google高级搜索命令

一、allintitle:当我们用allintitle提交查询的时候&#xff0c;Google会限制搜索结果仅是那些在网页标题里边包含了我们所有查询关键词的网页。例 &#xff3b;allintitle: detect plagiarism&#xff3d;&#xff0c;提交这个查询&#xff0c;Google仅会返回在网页标题里边包含…

Springboot遇到的问题

Springboot遇到的问题1_访问4041.1_url错误1.2_controller和启动项不在同级目录1.3_未加ResponseBody2_字母后端显示大写&#xff0c;传到前端变为小写2.1_Data注释问题1_访问404 1.1_url错误 1.2_controller和启动项不在同级目录 1.3_未加ResponseBody 在方法上面加&#…

45 张图深度解析 Netty 架构与原理

作为一个学 Java 的&#xff0c;如果没有研究过 Netty&#xff0c;那么你对 Java 语言的使用和理解仅仅停留在表面水平&#xff0c;会点 SSH 写几个 MVC&#xff0c;访问数据库和缓存&#xff0c;这些只是初等 Java 程序员干的事。如果你要进阶&#xff0c;想了解 Java 服务器的…

ajax实现浏览器前进后退-location.hash与模拟iframe

为什么80%的码农都做不了架构师&#xff1f;>>> Aajx实现无数据刷新时&#xff0c;我们会遇到浏览器前进后退失效的问题以及URL不友好的问题。 实现方式有两种 1、支持onhashchange事件的&#xff0c;通过更新和读取location.hash的方式来实现 /* 因为Javascript对…

java环境变量配置以及遇到的一些问题

java环境变量配置以及遇到的一些问题1_下载2_配置环境变量2.1_配置JAVA_HOME2.2_配置CLASS_PATH2.2_配置系统路径PATH3_遇到的问题3.1_输入java -version无效3.2_javac无效1_下载 2_配置环境变量 打开我的电脑&#xff0c;右击空白处点击属性 点击高级系统设置 点击环境变量…

c fputc 函数重写_使用示例的C语言中的fputc()函数

c fputc 函数重写C中的fputc()函数 (fputc() function in C) Prototype: 原型&#xff1a; int fputc(const char ch, FILE *filename);Parameters: 参数&#xff1a; const char ch, FILE *filenameReturn type: int 返回类型&#xff1a; int Use of function: 使用功能&a…

登陆 tomcat manager

想进去很简单 就在tomcat的配置文件 conf/tomcat-user.xml中加入 <role rolename"manager-gui"/><user username"dev" password"dev" roles"manager-gui"/> /* 而<role rolename"manager-gui"/>是指拥…

信息系统状态过程图_操作系统中的增强型过程状态图

信息系统状态过程图The enhanced process state diagram was introduced for maintaining the degree of multiprogramming by the Operating System. The degree of multiprogramming is the maximum number of processes that can be handled by the main memory at a partic…

Java中竟有18种队列?45张图!安排

今天我们来盘点一下Java中的Queue家族&#xff0c;总共涉及到18种Queue。这篇恐怕是市面上最全最细讲解Queue的。本篇主要内容如下&#xff1a;本篇主要内容帮你总结好的阻塞队列&#xff1a;18种Queue总结一、Queue自我介绍 队列原理图1.1 Queue自我介绍hi&#xff0c;大家好&…

ssh框架常见错误与解决方法

1.Class not Found Exception 异常.---->解决方法&#xff1a;在lib中加入两个jar包&#xff08;spring.jar与struts2- spring-plugin-2.1.8.1.jar&#xff09;&#xff1b;2.使用hql语句时出现java.lang.reflect.InvocationTargetException(即使用hql回调函数带参数时) 或…

使用gzip优化web应用(filter实现)

相关知识&#xff1a; gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后&#xff0c;通常情况下服务器端会将页面文件和其他资源&#xff0c;返回到客户端&#xff0c;客户端加载后渲染呈现&#xff0c;这种情况文件一般都比较大&#xff0c;如果开启Gzip …

肯德尔相关性分析_肯德尔的Tau机器学习相关性

肯德尔相关性分析Before we begin I hope you guys have a basic understanding of Pearson’s and Spearmans correlation. As the name suggests this correlation was named after Maurice Kendall in the year 1938. 在开始之前&#xff0c;我希望你们对皮尔逊和斯皮尔曼的…

40 张图带你搞懂 TCP 和 UDP

我们本篇文章的组织脉络如下运输层位于应用层和网络层之间&#xff0c;是 OSI 分层体系中的第四层&#xff0c;同时也是网络体系结构的重要部分。运输层主要负责网络上的端到端通信。运输层为运行在不同主机上的应用程序之间的通信起着至关重要的作用。下面我们就来一起探讨一下…