我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Scala中优雅的处理Null问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Scala中优雅的处理Null问题

前言

如果在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 (不过它是写出发生问题的原因)

还是搞一段代码来解释



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内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Scala中优雅的处理Null问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue中如何优雅地处理组件间的通信问题?

Vue中组件间通信指南:父子组件:Props(单向传递数据)和Events(子组件触发事件)兄弟组件:EventBus(全局事件总线)和Vuex(集中式状态管理)非父子组件:provide/inject(注入数据)、插槽(组件内嵌)插槽:允许子组件内容注入父组件,作用域插槽可访问父组件数据和方法组合API:useEmit()、useProvide()等,提供简洁的通信方式最佳实践:保持组件解耦、明确事件名称、使用数据流图、避免过度通信、使用Vuedevtools调试
Vue中如何优雅地处理组件间的通信问题?
2024-04-02

PyCharm技巧:优雅处理代码自动换行问题

PyCharm技巧:优雅处理代码自动换行问题在使用PyCharm进行Python编程的过程中,经常会遇到代码自动换行的问题,特别是当一行代码过长时,自动换行可能会影响代码的可读性和美观性。如何优雅地处理这个问题,让代码更加整洁和易读呢?本
PyCharm技巧:优雅处理代码自动换行问题
2024-02-23
处理 VUE 异步组件的常见问题:优雅解决遇到的挑战
2024-03-09

Java访问者模式实现优雅的对象结构处理

Java访问者模式是一种行为型设计模式,它通过将数据结构和数据操作分离,实现对复杂对象结构的处理。它将数据结构中的每个元素都转换为访问者能够识别的形式,从而使得数据操作可以在不影响数据结构的前提下进行扩展和变化
2023-05-17

Vuex中actions优雅处理接口请求的方法

在项目开发中,如果使用到了vuex,通常我会将所有的接口请求单独用一个文件管理,这篇文章主要介绍了Vuex中actions如何优雅处理接口请求,业务逻辑写在actions中,本文给大家分享完整流程需要的朋友可以参考下
2022-11-16

如何优雅地处理golang函数中的错误

在 golang 中使用 customerror 类型可以优雅地处理函数中的错误,为您提供:自定义错误消息以提供更多详细信息。错误分类以将错误分组到类别中。错误堆栈跟踪以帮助追踪错误的根源。如何通过 Golang 的 CustomError
如何优雅地处理golang函数中的错误
2024-04-24

Python中优雅处理JSON文件的方法是什么

这篇文章给大家介绍Python中优雅处理JSON文件的方法是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 引言我们将学习如何使用Python读取、解析和编写JSON文件。我们将讨论如何最好地处理简单的JSON
2023-06-22

Vue中如何优雅地处理组件的销毁与清理?

优雅地处理Vue组件的销毁与清理至关重要。利用beforeDestroy生命周期钩子执行清理操作,并使用mounted钩子保存资源。destroyed钩子用于释放资源,v-on:beforeDestroy指令和Vuex可简化清理。避免使用setTimeout和setInterval,考虑第三方库或GC标记。单元测试验证组件销毁和清理行为。遵循最佳实践,例如响应式数据和显式释放资源,以防止内存泄漏。
Vue中如何优雅地处理组件的销毁与清理?
2024-04-02

python的中文处理问题

1.问题,包含中文的python脚步,运行时报这个错误SyntaxError: Non-ASCII character '\xe6' in file test_zh.py on line 6, but no encoding declare
2023-01-31

Vue中如何优雅地处理组件的依赖注入?

Vue提供多种依赖注入方式,包括服务注入、依赖性注入容器、依赖关系传值和插件系统。最佳实践取决于应用程序需求:可访问性:服务注入提供全局访问,而其他方式更适用于特定组件。测试性:容器和传值通过模拟依赖关系提高了测试性。模块化:容器提供了明确的依赖关系管理系统。性能:服务注入最快,而容器和传值可能带来开销。通过选择最适合您用例的技术,您可以优雅地处理Vue中的组件依赖注入,提升代码的可维护性、可测试性和性能。
Vue中如何优雅地处理组件的依赖注入?
2024-04-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录