Scala中优雅的处理Null问题

目录
  • 前言
  • 什么是Option
  • 煮个栗子
  • Option的好处不仅如此
  • 简单的总结java null 与 scala Option
  • Option的缺点
  • Either Left Right简介与使用

前言

如果在scala代码还在使用ids!=null,可能会被有的人嘲笑,都什么年代了,竟然还有这样的写法,NullPointerException见少了吧?
不过,据统计:
Spark 源代码使用了 821 次 Option 关键字,但它也直接在像if (ids != null)。

Spark 采用混合方式,大部分情况下使用 Option,但个别时候出于性能(这里主要是为了给使用这返回提示信息)原因才使用了null。

一个很好的习惯是当有方法返回值可能为null的时候,使用Option来代替。

什么是Option

标准类库中Option类型用样例类来表示那种可能存在、也可能不存在的值
Option的有两个子类,Some 和 None,Some包装了某个值,如Some(“Jack”),而None表示没有值。

有的小伙伴看到依然云里雾里的,因此直接上一个简单的例子,来感受一下这个Option究竟是什么东西:

煮个栗子

这里写了一个把字符串转为数值的方法,输入的是字符串,输出的这里注意一下,并不是直接输出Int,而且一个泛型为Int的Option

def toInt(in: String): Option[Int] = {
  try {
    Some(Integer.parseInt(in.trim))
  } catch {
    case e: NumberFormatException => None
  }
}

如何使用这个函数:

toInt("s") match {
  case Some(i) => println(i)
  case None => println("您输入的字符串无法转为数字")
}

简单的总结一下这个Option的使用,其实就是把你原本要返回的类型,直接返回泛型为该类型的Option,然后写正常返回值的时候返回Some,异常的时候返回None即可。而调用方法的时候,需要用到match case分别做处理。

有人看到这里可能会抱怨:一个简单的null判断,写了这么一大堆,还不如java中的直接用i!=null来判断简单粗暴呢。

但是如果这个toInt函数是别人写的,你是个使用者,你一定会遇到如下问题:

  • 你没有读API文档,根本不知道toInt可能会返回一个null,并且可能你写的代码会抛出NullPointerException
  • 你读了API文档,并且也有很多使用这个函数的经验,知道它可能会返回null,因此你肯定会写如下代码来处理可能出现的空指针异常
Integer i = toInt(someString);
if (i == null) {
    System.out.println("您输入的字符串无法转为数字");
} else {
    System.out.println(i);
}

该代码并不比 Scala的Option和match方法差,但你确实必须阅读API文档才能知道必须得这样处理。

3.当然还可以通过抛出NumberFormatException来处理null或者其他一些异常情况

Option的好处不仅如此

比如想统计下面list中的总和,这些字符串有的可以转为Int,有的不可以

val bag = List("1", "2", "foo", "3", "bar")

要实现这个需求,感觉要写很多代码才能实现,其实在scala中只要一行代码就可以实现:

val sum = bag.flatMap(toInt).sum

为什么可以这么简单的就实现:
我们的toInt方法返回的是Some[Int]或None,而flatMap知道如何处理这些值,所以实现起来就小菜一碟了,而且还很容易阅读和理解。

这就是使用Option/Some/None 模式真正牛叉的地方了

简单的总结java null 与 scala Option

如果你用别人写的java方法,那么一般需要阅读API文档,或者是使用后抛出了NullPointException后,查文档和资料发现,需要处理这个空指针异常。那么scala Option我们在使用函数的时候,可以看到返回值是个Option[Int](直接在IDE中就能看到返回值类型,不需要去阅读该函数的API文档),说明开发这个函数的人一定用了Option/Some/None这一套组合拳,因此就知道用match case来解决了。

在我看来,其实从写代码的角度来看代码量并没有减少,优点有两:

  • 更具有可读性,
  • 避免在使用函数的时候,出现空指针异常 Option的缺点

Option的缺点

有的人会说,你前言中都说了连spark源码都不是一律采用Option来处理null值,你既然上面吹的神乎其神的,人家干嘛不全部用Option?
这里就得说一下Option的一个缺点:
无法说出某件事失败的原因(也就是为什么你得到了一个None而不是一个Some),因为根本就看不到错误异常信息

对此scala 的解决方案是使用Either Left 和 Right来处理异常信息

Either Left Right简介与使用

Either其实用起来和Option很像,不同的是Either可以返回一个字符串来描述发生的问题。

Either 和Option的比较:
Either 就像 Option
Right 就像 Some
Left 就像 None (不过它是写出发生问题的原因)

还是搞一段代码来解释

/**
  * 这里写个简单的方法来演示,如何写一个返回值为Either的方法
  * 以及Either中Left和Right的用法
  */
def divideXByY(x: Int, y: Int): Either[String, Int] = {
  if (y == 0) Left("零不能作为除数")
  else Right(x / y)
}

// 使用 Either, Left, and Right的几种不同方式
println(divideXByY(1, 0))
println(divideXByY(1, 1))
divideXByY(1, 0) match {
  case Left(s) => println("Answer: " + s)
  case Right(i) => println("Answer: " + i)
}

上面divideXByY方法返回的是一个Either[String, Int],这个泛型String就是Left方法中传入的数据类型,而Int就是Right方法传入的数据类型。

通过上面的例子,会发现这一套东西和Option/Some/None使用起来很像,唯一不同的是,Either将出错的信息可以传回,使用者可以看到异常信息。我们看看官网是怎么说的:

Represents a value of one of two possible types (a disjoint union.) Instances of Either are either an instance of Left or Right.
A common use of Either is as an alternative to Option for dealing with possible missing values. In this usage,
scala.None is replaced with a Left which can contain useful information. Right takes the place of Some.
Convention dictates that Left is used for failure and Right is used for success.
说白了就是我上面写的,如果要返回错误信息给使用者,就用Either。不过根据我经验,一般这样的场景不算多。因此最长用的还是Option。

到此这篇关于Scala中如何优雅的处理Null的文章就介绍到这了,更多相关Scala处理Null内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 在IntelliJ IDEA中创建和运行java/scala/spark程序的方法

    本文将分两部分来介绍如何在IntelliJ IDEA中运行Java/Scala/Spark程序: 基本概念介绍 在IntelliJ IDEA中创建和运行java/scala/spark程序 基本概念介绍 IntelliJ IDEA 本文使用版本为: ideaIC-2020.1 IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境.IntelliJ在业界被公认为最好的java开发工具,它的旗舰版本还支持HTML,CSS,PHP,MySQL,Python等,免费版只支持Jav

  • break在scala和java中的区别解析

    这篇文章主要介绍了break在scala和java中的区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 scala中的break和java中的break作用是一样的,都是跳出循环,只两者的用法不太一样. 1.scala中break中的用法import scala.util.control.Breaks import scala.util.control.Breaks object breakDemo { //break在scala中的使用

  • 详解Java中的scala正则表达式

    Scala 通过 scala.util.matching 包中的 Regex 类来支持正则表达式. eg:使用正则表达式查找单词 Scala 实例中使用 String 类的 r() 方法构造了一个Regex对象.(也可直接new一个Regex对象实例)然后使用 findFirstIn 方法找到首个匹配项.如果需要查看所有的匹配项可以使用 findAllIn 方法. 可以使用 mkString( ) 方法来连接正则表达式匹配结果的字符串,并可以使用管道(|)来设置不同的模式: 如果需要将匹配的文本

  • Java 和 Scala 如何调用变参

    Java 和 Scala 都支持变参方法, 写在最后的位置上,最基本的调用方式也都是一样的,一个个罗列过去.也可以传入数组参数,因为变参本质上就是一个数组,就是把 ... 开始位置到最后一个参数都收纳到数组中去,所以变参之所以要放在最后的位置上,且一个方法中最多只能有一个变参类型. 这里主要是对比 Scala 对变参方法的调用,基本调用法当然是没问题的,但是在传入数组作为变参的参数列表与 Java 相对时就稍有变化了. 另外提一下,如果想传入 List 作为变参列表,而不是整体作为变参的第一个元

  • Java开发工具-scala处理json格式利器-json4s详解

    1.为什么是json4s 从json4s的官方描述 At this moment there are at least 6 json libraries for scala, not counting the java json libraries. All these libraries have a very similar AST. This project aims to provide a single AST to be used by other scala json librar

  • 深入学习java中的Groovy 和 Scala 类

    前言 Java 传承的是平台,而不是语言.有超过 200 种语言可以在 JVM 上运行,它们之中不可避免地会有一种语言最终将取代 Java 语言,成为编写 JVM 程序的最佳方式.本系列将探讨三种下一代 JVM 语言:Groovy.Scala 和 Clojure,比较并对比新的功能和范例,让 Java 开发人员对自己近期的未来发展有大体的认识. Java 语言的开发人员精通 C++ 和其他语言,包括多继承(multiple inheritance),使得类可以继承自任意数量的父类.多继承带来的一

  • Scala中优雅的处理Null问题

    目录 前言 什么是Option 煮个栗子 Option的好处不仅如此 简单的总结java null 与 scala Option Option的缺点 Either Left Right简介与使用 前言 如果在scala代码还在使用ids!=null,可能会被有的人嘲笑,都什么年代了,竟然还有这样的写法,NullPointerException见少了吧? 不过,据统计: Spark 源代码使用了 821 次 Option 关键字,但它也直接在像if (ids != null). Spark 采用混

  • 浅析Java和Scala中的Future

    随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue,带你走入异步编程的大门. Future 很多同学可能会有疑问,Futrue跟异步编程有什么关系?从Future的表面意思是未来,一个Future对象可以看出一个将来得到的结果,这就和异步执行的概念很像,你只管自己去执行,只要将最终的结果传达给我就行,线程不必一直暂停等待结果,可以在具体异步任务执行的时候去执行其他操作

  • Spring Boot中优雅的获取yml文件工具类

    如何在spring boot中优雅的获取.yml文件工具类呢 代码如下: package com.common.base.utils.base; import com.common.base.generator.ResourceManager; import org.yaml.snakeyaml.Yaml; import java.io.InputStream; import java.util.HashMap; import java.util.Map; /** * yml文件工具类 */ p

  • 如何在Spring Boot应用中优雅的使用Date和LocalDateTime的教程详解

    Java8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作.SimpleDateFormat不是线程安全的,而Date处理时间很麻烦,所以Java8提供了LocalDateTime.LocalDate和LocalTime等全新的时间操作API.无论是Date还是LocalDate,在开发Spring Boot应用时经常需要在每个实体类的日期字段上加上@DateTimeFormat注解来接收前端传值与日期字段绑定,加上@JsonFormat注

  • Spring/Spring Boot 中优雅地做参数校验拒绝 if/else 参数校验

    数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 最普通的做法就像下面这样.我们通过 if/else 语句对请求的每一个参数一一校验. @RestController @RequestMapping("/api/person") public class PersonController { @PostMapping public ResponseEnti

  • Vue后台中优雅书写状态标签的方法实例

    目录 前言 优化 二次封装 el-tag 组件 使用 总结 前言 在后台系统开发中,对于列表,常常有一些状态字段的展示,比如审核状态.退货申请状态等等,并且往往伴随有状态筛选的列表查询条件,同时状态显示对应不同颜色,在写代码时有些人往往是这么做的: <template> <el-form :model="query"> <el-form-item label="审批状态" prop="status"> <

  • 一篇文章带了解如何用SpringBoot在RequestBody中优雅的使用枚举参数

    目录 确认需求 定义枚举和对象 实现转换逻辑 方案一:精准攻击 方案二:全范围攻击 测试 总结 确认需求 需求与前文类似,只不过这里需要是在 RequestBody 中使用.与前文不同的是,这种请求是通过 Http Body 的方式传输到后端,通常是 json 或 xml 格式,Spring 默认借助 Jackson 反序列化为对象. 同样的,我们需要在枚举中定义 int 类型的 id.String 类型的 code,id 取值不限于序号(即从 0 开始的 orinal 数据),code 不限于

  • Python中优雅处理JSON文件的方法实例

    目录 1. 引言 2. 什么是JSON文件? 3. 使用Python处理JSON文件 3.1. 将JSON文件读取为字典类型 3.2. 将JSON文件读取为Pandas类型 3.3. 使用Pandas读取嵌套JSON类型 3.4. 访问特定位置的数据 3.5. 导出JSON 3.6. 格式化输出 3.7. 输出字段排序 4.总结 5.参考 1. 引言 在本文中,我们将学习如何使用Python读取.解析和编写JSON文件. 我们将讨论如何最好地处理简单的JSON文件以及嵌套的JSON文件,当然我们

  • asp.net core 中优雅的进行响应包装的实现方法

    目录 摘要 正常响应包装 实现按需禁用包装 总结 摘要 在 asp.net core 中提供了 Filter 机制,可以在 Action 执行前后进行一些特定的处理,例如模型验证,响应包装等功能就可以在此基础上实现,同时也提供了 ApplicationModel API, 我们可以在此基础上实现选择性的添加 Filter,满足部分接口需要响应特定的结构, 我们常见的 [AllowAnonymous] 正是基于这种机制.同时也将介绍如何让 Swagger 展示正确的包装响应体,以满足第三方对接或前

  • 如何在React项目中优雅的使用对话框

    目录 背景 场景一 场景二 场景三 问题一:难以扩展 问题二:维护问题 问题的本质 对话框的本质 全局的状态管理的对话框 整体的架构 具体实现 Redux - reducer 存储 Redux - action 处理对话框的显示隐藏 Hook - useCommonModal 创建对话框-容器模块 对话框返回值处理 运行实例 总结 参考 背景 对话框在前端开发应用中,是一种非常常用的界面模式.对话框作为一个独立的窗口,常常被用于信息的展示,输入信息,亦或者更多其他功能.但是项目的使用过程中,在某

随机推荐