动手选择值

由于冠状病毒的存在,可选的东西在空中,一切都变得可选,例如可选的公共聚会,可选的在家工作,可选的旅行等。

我现在是时候谈论处理NULL引用的软件工程中真正的“ 可选 ”了。

托尼·霍尔(Tony Hoare)坦言,他发明了空(Null)犯了数十亿美元的错误。 如果您还没有看过他的演讲,那么我建议您看一下Null-References-The-Billion-Dollar-Mistake 。

我将与null分享一些反模式 ,以及如何使用Optional或MayBe之类的抽象方法解决它。

在此示例中,我们将使用可以包含一些空值的简单值对象。

public class Person {final String firstName;final String lastName;final String email; // This can be nullfinal String phone; //This can be null
}

该值对象的电子邮件和电话号码可以为空值。

方案:电子邮件和电话号码上的联系人

不使用可选

第一次尝试将基于检查null,如下所示

//Not using optionalif (p.email != null) {System.out.println("Sending email to " + p.email);}if (p.phone != null) {System.out.println("Calling " + p.phone);}

这就是多年来所做的。 具有收集结果的另一种常见模式。

List<Person> p = searchPersonById("100");if (p.isEmpty()) {System.out.println("No result");} else {System.out.println("Person" + p.get(0));}

以错误的方式使用可选

Optional<String> phone = contactNumber(p);Optional<String> email = email(p);if (phone.isPresent()) {System.out.println("Calling Phone " + phone.get());}if (email.isPresent()) {System.out.println("Sending Email " + email.get());}

这样做好一点,但是通过在代码中添加if / else块,将Optional的所有好处都抛弃了。

永远快乐可选

//Always HappyOptional<String> phone = contactNumber(p);Optional<String> email = email(p);System.out.println("Calling Phone " + phone.get());System.out.println("Sending Email " + email.get());

很高兴感到高兴,但是当您尝试使用Optional时,您所做的假设很大,或者您不需要Optional。

嵌套属性可选

在这种情况下,我们将扩展Person对象并添加Home属性。 并非每个人都可以拥有房屋,因此最好不要使用该房屋。 让我们看看在这种情况下联系人场景如何工作

//Nested Propertyif (p.getHome() != null) {System.out.println("Sending Postal mail " + p.getHome().address);}if (p.getHome() != null && p.getHome().getInsurance() != null) {System.out.println("Sending Notification to insurance " + p.getHome().getInsurance().getAgency());}

在这里,代码将具有大量嵌套的空检查变得越来越糟。

基于优先级的默认

对于这种情况,我们首先尝试通过家庭住址与他人联系,如果该人不可用,则请通过办公地点与他人联系。

//Address has priority , first home and then Officeif (p.home != null) {System.out.println("Contacted at home address " + p.home.address);return; // Magical return for early exit}if (p.office != null) {System.out.println("Contacted at office address " + p.office.address);return; // Magical return for early exit}

这种类型的场景需要使用提前控制流来尽早返回,并使代码难以理解和维护。

这些是一些常见模式,其中未使用可选选项或使用了错误的方式。

可选使用方式

让我们看看一些使用可选的好方法。

根据领域知识使属性可选

使属性成为可选属性非常容易。

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

是的,允许将其设为“可选”,没有人会为此而绞尽脑汁,并且可以毫无恐惧地随意这样做。 更改完成后,我们可以编写如下内容

//Use Optionalp.getEmail().ifPresent(email -> System.out.println("Sending email to " + email));p.getPhone().ifPresent(phone -> System.out.println("Calling " + phone));//Optional for Collection or Search type of requestOptional

It looks neat, first step to code without explicit if else on application layer.

Use some power of Optional

//Use IfPresent & other cool thingsphone.filter(number -> hasOptIn(number)).ifPresent(number -> System.out.println("Calling Phone " + number));email.filter(m -> hasOptIn(m)).ifPresent(m -> System.out.println("Sending Email " + m));

Optional is just like stream, we get all functional map,filter etc support. In above example we are checking for OptIn before contacting.

Always happy optional

Always happy optional that calls "get" without check will cause runtime error on sunday midnight, so it advised to use ifPresent

//Don't do thisSystem.out.println("Calling Phone " + phone.get());System.out.println("Sending Email " + email.get());//Use ifPresent to avoid runtime errorphone.ifPresent(contact -> System.out.println("Sending email to " + contact));email.ifPresent(contact -> System.out.println("Calling " + contact));

Nested Optional

p.getHome().ifPresent(a -> System.out.println("Sending Postal mail " + a.address));p.getHome().flatMap(Person.Home::getInsurance).ifPresent(a -> System.out.println("Sending Notification to insurance " + a.agency));

Flatmap does the magic and handles null check for home and convert  insurance object also.

Priority based default

//Address has priority , first home and then OfficeOptional<String> address = Stream.of(person.getHome().map(Home::getAddress), person.getOffice().map(Office::getAddress)).filter(Optional::isPresent).map(Optional::get).findFirst();address.ifPresent(add -> System.out.println("Contacting at address " + add));

This example is taking both home & office address and pick the first one that has value for sending notification. This particular pattern avoids lots of nested loops.

Else branch

Optional has lots of ways to handle else part of the scenario like returning some default value(orElse) , lazy default value (orElseGet) or throw exception(orElseThrow).

What is not good about optional

Each design choice has some trade off and optional also has some. It is important to know what are those so that you can make careful decision.

Memory indirection

As optional is container , so every access to value need extra jump to get real value. Optional is not good choice for element in array or collection.

No serialization

I think this is good decision by Jdk team that does not encourage people to make instance variable optional. You can wrap instance variable to Optional at runtime or when required for processing.

翻译自: https://www.javacodegeeks.com/2020/03/hands-on-optional-value.html

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

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

相关文章

wincc历史数据库_WinCC系统的基本功能介绍——自动化工程师必备

写在面前前面讲解了西门子的TIA Portal Wincc, Wincc Classic和Wincc OA (一文带你了解西门子Wincc),介绍了西门子的超大型/分布式SCADA系统Wincc OA(初识西门子Wincc OA——超大型/分布式SCADA)&#xff0c;还介绍了Wincc Classic的典型架构和选型指南(WinCC V7.5典型架构及选…

apache.camel_Apache Camel 2.14中的更多指标

apache.camelApache Camel 2.14将于本月晚些时候发布。 由于正在解决某些Apache基础结构问题&#xff0c;因此存在一些问题。 这篇博客文章讨论的是我们添加到此版本中的新功能之一。 感谢Lauri Kimmel捐赠了骆驼指标组件&#xff0c;我们将其与出色的Codehale指标库集成在一起…

依赖管理和Maven

Maven伟大而成熟。 几乎所有事物都总有解决方案。 您可能在组织项目上遇到的主要情况是依赖管理。 而不是每个项目都没有自己的依赖关系&#xff0c;您需要一种集中化的方式来继承那些依赖关系。 在这种情况下&#xff0c;您可以在父舞会上声明托管依赖项。 在我的示例中&…

linux ps 代码,Linux ps命令详解(示例代码)

ps命令是Process Status的缩写, 用来列出系统中当前运行的那些进程. ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令ps常见命令参数********* simple selection ******…

Apache Kafka消费者再平衡

消费者重新平衡决定哪个消费者负责某些主题的所有可用分区的哪个子集。 例如&#xff0c;您可能有一个包含20个分区和10个使用者的主题。 在重新平衡结束时&#xff0c;您可能希望每个使用者都从2个分区中读取数据。 如果关闭了这些使用者中的10个&#xff0c;则可能会期望每个…

linux系统ll历史,Linux操作系统原理笔记

在Linux操作系统内核内部&#xff0c;进程是通过一个链表&#xff0c;而且是一个双向链表来管理的。进程描述符&#xff1a;每一个进程都有其描述符&#xff0c;每一个描述符彼此之间都有关联性的。双向链表&#xff1a;一个进程内部可能包含多个线程。上下文切换(Context swtc…

java工程师的终极书单_Java 9 –终极功能列表

java工程师的终极书单这篇文章将针对即将到来的Java 9版本进行更新&#xff0c;新增功能 &#xff08; 最新更新&#xff1a;2014年 9月9日 &#xff09; OpenJDK开发正在加快速度&#xff1a;2014年3月Java 8发布后&#xff0c;我们预计将进入2年的发布周期。 据报道&#xf…

称之为例外?

尽管这是一个与测试和Wiremock有关的Java示例&#xff0c;但它涉及一个更普遍的问题。 我们正在尝试重试Wiremock的verify方法&#xff0c;该方法可能会在我们要检查的端点被命中之前由测试调用。 在这种情况下&#xff0c;我们想在几秒钟后重试一次直到超时。 有趣的是&#…

c语言字符大于等于怎么打,c语言大于等于怎么打?

c语言大于等于怎么打&#xff1f;C语言‘大于等于符号是“>”&#xff1b;“>”是关系运算符用于比较运算。包括大于(>)、小于()、小于等于(<)和不等于(!)六种。注意要在英文的输入状态下写c代码。知识拓展&#xff1a;C语言运算符号指的是运算符号。C语言中的符号…

用c语言编写的源文件经过编译,若没有产生编译错误,则系统将,用 C 语言编写的源文件经过编译,若没有产生编译错误,则系统将(??)...

用C语言有产译错拖拉动工:旋是用一种耕机耕作机(件的机具智慧职教作部)驱。编写编译标准是消商品衡量和品价格价值质的直接费者。文件误则单反卡为相机用的最常存储。能给您提网球的(大力拍上量)是供最在击球时&#xff0c;的手的一使你舒服又能域感最个区。的是下列说法正确&a…

junit:junit_简而言之,JUnit:Hello World

junit:junit对于Java世界中的开发人员而言&#xff0c; JUnit似乎是最受欢迎的测试工具 。 因此&#xff0c;难怪就此主题已经写了一些好书 。 但是&#xff0c;通过以顾问为生&#xff0c;我仍然经常遇到程序员&#xff0c;他们至多对工具及其正确用法都不了解。 因此&#x…

android 多个复选框,Android UI控件之CheckBox(复选框、多选框)

上一篇文章中学习了RadioButton。知道了RadionButton的基本用法&#xff0c;实现起来也是听简单的和RadioButton一样CheckBox也是一个使用的非常多的控件&#xff0c;Android中它的的用法也挺简单的。以一个例子程序为例&#xff1a;同样先看一个常规的实现&#xff1a;布局文件…

android调用虚拟摄像头方法,Android:如何在模拟器中使用网络摄像头?

我通过在AVD Manager中将前置摄像头设置为“ webcam0”将摄像头连接到仿真器。 启动模拟器的相机应用程序时&#xff0c;出现错误CameraService::connect X (pid 702) rejected (invalid cameraId 0).这是Android源代码的相关部分&#xff1a;sp CameraService::connect(const …

神话般的代码

考虑以下代码段&#xff1a; int max 10; int a 0; while (true) {// do a thing that may result in an early return if (a > max) {break;} }throw new RuntimeException("It ran out of attempts");上面有一些WTF。 循环有点不可思议&#xff0c;控制流似乎…

android listview asynctask,Android精通之AsyncTask与ListView讲解

版权声明&#xff1a;未经博主允许不得转载标题图AsyncTask了解AsyncTask异步&#xff0c;需要了解一下异步任务(多线程)&#xff0c;什么是线程&#xff0c;可以这么说线程好比边吃饭边看电视&#xff0c;AsyncTask是为了方便后台线程中操作更新UI&#xff0c;本质为Handler异…

打破了vs你错了

为微服务构建REST API时&#xff0c;需要做出一些关于响应的设计决策。 某些响应显然是微服务周围协议的产物–例如3xx代码之类的东西都与重定向和路由有关。 通常&#xff0c;您将尝试获取正确的2xx代码以取得成功。 如有疑问&#xff0c;将为200&#xff08;确定&#xff09…

android lable标签,android:label说明

文章目录1. 说明android:label 用于app 在切换activity的时候,自动更换左上角的显示2. 代码架构3. String.xml 字符串资源文件My Application主界面 labsecond 界面 lab4. AndroidMainfest.xmlpackage"com.example.myapplication">android:allowBackup"true&…

Neo4J OGM与Quarkus

在下面的视频中&#xff0c;我演示了一个使用Neo4J数据库和Neo4J OGM的Quarkus应用程序示例。 看一下GitHub上的示例项目 。 我为咖啡豆创建了一个示例域&#xff0c;其中包含我们可以查询和匹配的某些风味配置文件。 红色节点是来自某个国家/地区的咖啡豆&#xff0c;味道像…

鸿蒙os内测版应用名称,谁知道报名鸿蒙系统公测,应用名称怎么填的?

[分享交流]谁知道报名鸿蒙系统公测&#xff0c;应用名称怎么填的&#xff1f;92209电梯直达huafen327001442初窥门径发表于 2020-12-18 21:17:21来自&#xff1a;HUAWEI Mate 30 Pro 5G最新回复 2020-12-26 21:47:39Screenshot_20201218_210913_com.tencent.mm_edit_1719993392…

命令模式应用_命令设计模式的应用

命令模式应用嗨&#xff0c;您好&#xff01; 今天&#xff0c;我将与您分享一种非常出色的编程设计模式。 它有很多用法&#xff0c;是我的最爱之一。 编程设计模式命令具有多种用例。 在这篇文章中&#xff0c;我们将看到如何实现来自现实世界的东西。 我们将使用电子汽车钥…