Scala avoid null

Scala avoid null

在Java里, NullPointerException不知道会在什么时候发生,导致代码到处都是判断null的情况。比如如下例子,

val stateCapitals = Map(
  "Alabama" -> "Montgomery",
  "Alaska" -> "Juneau",
  "Wyoming" -> "Cheyenne")
println("Get the capitals wrapped in Options:")
println("Alabama: " + stateCapitals.get("Alabama"))
println("Wyoming: " + stateCapitals.get("Wyoming"))
println("Unknown: " + stateCapitals.get("Unknown"))
println("Get the capitals themselves out of the Options:")
println("Alabama: " + stateCapitals.get("Alabama").get)
println("Wyoming: " + stateCapitals.get("Wyoming").getOrElse("Oops!"))
println("Unknown: " + stateCapitals.get("Unknown").getOrElse("Oops2!"))

输出打印,

C:\WorkSpace5-gitosc\scala-showcase\src\main\java\com\usoft2>scala main3.scala

Get the capitals wrapped in Options:

Alabama: Some(Montgomery)

Wyoming: Some(Cheyenne)

Unknown: None

Get the capitals themselves out of the Options:

Alabama: Montgomery

Wyoming: Cheyenne

Unknown: Oops2!


Scala的Option类型

为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。在没有值的时候,使用None,这是Option的一个子类。如果有值可以引用,就使用Some来包含这个值。Some也是Option的子类。

None被声明为一个对象,而不是一个类,因为我们只需要它的一个实例。这样,它多少有点像null关键字,但它却是一个实实在在的,有方法的对象。


应用例子

Option类型的值通常作为Scala集合类型(List,Map等)操作的返回类型。比如Map的get方法:

scala> val capitals = Map("France"->"Paris", "Japan"->"Tokyo", "China"->"Beijing")
capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo, China -> Beijing)

scala> capitals get "France"
res0: Option[String] = Some(Paris)

scala> capitals get "North Pole"
res1: Option[String] = None

scala>

Option有两个子类别,Some和None。当程序回传Some的时候,代表这个函式成功地给了你一个String,而你可以透过get()函数拿到那个String,如果程序返回的是None,则代表没有字符串可以给你。

在返回None,也就是没有String给你的时候,如果你还硬要调用get()来取得 String 的话,Scala一样是会抛出一个NoSuchElementException异常给你的。

我们也可以选用另外一个方法,getOrElse。这个方法在这个Option是Some的实例时返回对应的值,而在是None的实例时返回传入的参数。换句话说,传入getOrElse的参数实际上是默认返回值。

scala> capitals get "North Pole" get
warning: there was one feature warning; re-run with -feature for details
java.util.NoSuchElementException: None.get
  at scala.None$.get(Option.scala:344)
  at scala.None$.get(Option.scala:342)
  ... 33 elided

scala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Paris

scala>  (capitals get "North Pole") getOrElse "Oops"
res4: String = Oops

scala> capitals get "France" getOrElse "Oops"
res5: String = Paris

scala>

提示

Scala程序使用Option非常频繁,在Java中使用null来表示空值,代码中很多地方都要添加null关键字检测,不然很容易出现NullPointException。因此Java程序需要关心那些变量可能是null,而这些变量出现null的可能性很低,但一但出现,很难查出为什么出现NullPointerException。

Scala的Option类型可以避免这种情况,因此Scala应用推荐使用Option类型来代表一些可选值。使用Option类型,读者一眼就可以看出这种类型的值可能为None。

实际上,多亏Scala的静态类型,你并不能错误地尝试在一个可能为null的值上调用方法。虽然在Java中这是个很容易犯的错误,它在Scala却通不过编译,这是因为Java中没有检查变量是否为null的编程作为变成Scala中的类型错误(不能将Option[String]当做String来使用)。所以,Option的使用极强地鼓励了更加弹性的编程习惯。


详解Option[T]

在Scala里Option[T]实际上是一个容器,就像数组或是List一样,你可以把他看成是一个可能有零到一个元素的List。

当你的Option里面有东西的时候,这个List的长度是1(也就是 Some),而当你的Option里没有东西的时候,它的长度是0(也就是 None)。

for循环

scala> val map1 = Map("key1" -> "value1")
map1: scala.collection.immutable.Map[String,String] = Map(key1 -> value1)

scala>  val value1 = map1.get("key1")
value1: Option[String] = Some(value1)

scala> val value2 = map1.get("key2")
value2: Option[String] = None

scala> def printContentLength(x: Option[String]) {
     |   for (c <- x) {
     |     println(c.length)
     |   }
     | }
printContentLength: (x: Option[String])Unit

scala> printContentLength(value1)
6

scala> printContentLength(value2)

scala>

map操作

在函数式编程中有一个核心的概念之一是转换,所以大部份支持函数式编程语言,都支持一种叫map()的动作,这个动作是可以帮你把某个容器的内容,套上一些动作之后,变成另一个新的容器。现在我们考虑如何用Option的map方法实现length: xxx的输出形式:

先算出 Option 容器内字符串的长度

然后在长度前面加上 “length: “ 字样

最后把容器走访一次,印出容器内的东西

scala>  val map1 = Map("key1" -> "value1")
map1: scala.collection.immutable.Map[String,String] = Map(key1 -> value1)

scala>  val value1 = map1.get("key1")
value1: Option[String] = Some(value1)

scala> value1.map(_.length).map("length: " + _).foreach(println)
length: 6

scala>  value1.map("length: " + _.length).foreach(println)
length: 6

scala>

转载请注明作者Jason Ding及其出处

GitCafe博客主页(http://jasonding1354.gitcafe.io/)

Github博客主页(http://jasonding1354.github.io/)

CSDN博客(http://blog.csdn.net/jasonding1354)

简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

Google搜索jasonding1354进入我的博客主页

=============END=============

转载于:https://my.oschina.net/xinxingegeya/blog/487220

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值