由于我看了一下Option类可以帮助你避免NullPointerException异常的文章因此,我开始使用它所有的地方。想象一下这样的:

var file:Option[File] = None

和后,当我使用它:

val actualFile = file.getOrElse(new File("nonexisting"))
if(actualFile.getName.equals("nonexisting")) { // instead of null checking

}
else { // value of file was good

}

做这样的东西不觉得所有的“正确”给我。我还注意到,.get已成为过时。 。这有点东西你们与期权做什么太,还是我走错了路?

有帮助吗?

解决方案

这是一般不返回Option然后用getOrElse生产,意思是“未找到”的一些标记值是个好主意。这就是Option是专为:以表示值未找到

Option真正体现出它的功率与像mapforeach函数编程结构结合使用时。有多个选项时,这是最有效的。例如,假设我写这需要一个字符串,并给我回一个文件的方法,但只有当该文件存在,并且是一个文件不是一个目录:

import java.io._;
def niceFile1(s: String): File = {
  val f = new File(s);
  if (f.exists && !f.isDirectory) f else null
}
def niceFile2(s: String): Option[File] = {
  val f = new File(s);
  if (f.exists && !f.isDirectory) Some(f) else None
}

到目前为止,使用null更容易 - 至少直到你忘了,这可能会给你null,你会得到一个NPE。不管怎样,现在让我们尝试使用它。

def niceFopen1(s: String) = {
  val f = niceFile1(s);
  if (f!=null) new FileInputStream(f) else null;
}
def niceFopen2(s: String) = niceFile2(s).map(f => new FileInputStream(f))

看发生了什么事!在前一种情况下,我们不得不做手工逻辑测试和创建临时变量。啊!在第二种情况下,map做了所有的脏活我们:没有被映射到无,Some(file)被映射到Some(fileinputstream)。简单!

但它变得更好的。也许我们要找出一大堆文件的大小:

def totalSize2(ss: Seq[String]) = {
  (0L /: ss.flatMap(niceFile2)){(sum,f) => sum+f.length}
}

等待,这到底是怎么回事 - 怎么样所有None?难道我们没有注意,不知怎么处理?嗯,这就是flatMap进来:它合并所有的答案到一个列表。 None是长度为零的答案,因此它会忽略它。 Some(f)有一个答案 - f - 因此它把它在列表中。然后,我们用折叠加起来所有的长度 - 现在,在列表中的所有元素都是有效的。相当不错!

其他提示

这是一个好主意,为无法解决的的Option的价值,而是要的适用的逻辑,无论是它包含:

findFile.foreach(process(_))

基本上,如果找到一个这样处理一个File和不执行任何其它方式(并且等同于Thomas的第一for理解因为for编译为一个呼叫到foreach)。它是一个更简洁版本:

findFile match {
  case Some(f) => process(f)
  case None =>
}

更重要的是,关于这个伟大的事情是,你可以的的操作是这样的:

(findLiveFile orElse fileBackupFile orElse findTempFile).foreach(process(_)

在大多数情况下,你可以使用模式匹配

file match {
   case Some(f) => { .. } //file is there
   case _ => { .. } //file is not there 
}

如果你只在文件中有兴趣,如果它的存在,你可以使用一个表达

for(f <- file) { //file is there 
}

可以然后链表达式来在多个级别上工作,在容器上的

for{ 
  option <- List(Some(1), None, Some(2))
  f <- option
} yield f

res0: List[Int] = List(1, 2)

另外,您可以使用isDefined并获得:

if(option.isDefined) {
   val x = option.get;
} else {
}

得到的是未在Scala中弃用2.8.0.Beta-1。

下面是一种替代方案:

var file:Option[File] = None
// ...
file map (new File(_)) foreach { fh =>
  // ...
}

不过,如果你需要的,如果该文件存在,而其他的东西,如果不是这样,一个match说法是比较合适做一些事情:

var file:Option[File] = None
// ...
file map (new File(_)) match {
  case Some(fh) =>
    // ...
  case None =>
    // ...
}

这几乎是相同的作为if声明,但我喜欢它更好的链接性质的东西像Option,在这里我想提取的值也是如此。

晴重申大家都在说,但我觉得有,当你有一个可为空VAR这样你会遇到至少4种不同的情况:

1.文件不能为空

load(file.get())

当您尝试实际使用的文件会抛出异常。快速失败,耶!

2.文件为空,但是在这种情况下,我们有一个合理的默认:结果

load(file.getOrElse(new File("/defaultFile")))

3.两个逻辑的分支基于该文件是否存在:

  file match {
    case Some(f) => { .. } //file is there
    case _ => { .. } //file is not there 
  }

4.空操作,如果该文件是空,又名静默失败。我不认为这是一个非常往往是最好的我在现实生活中:

for (f <- file) {
//do some stuff
}

或者,也许更清楚?

if (f.isDefined) {
  //do some stuff
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top