如果调用Some(null),我应该如何抛出异常?

时间:2018-02-22 13:46:26

标签: scala idiomatic

我已完成Some(Option(null).get)但看起来有点奇怪。

更新了样本。我无法编译检查text是否为空。

object Code {
  def main(args: Array[String]): Unit = {
    println(computeSomething("good"))
    println(computeSomething(null))
    def computeSomething(text: String): Option[String] =
      Some(Option(text).get).map("not null text was [" + _ + "]")
  }
}
//System.out:
//
//Some(not null text was [good])
//Exception in thread "main" java.util.NoSuchElementException: None.get
//  at scala.None$.get(Option.scala:347)
//  at scala.None$.get(Option.scala:345)
//  at Code$.computeSomething$1(ZipInputLocation.scala:13)
//  at Code$.main(ZipInputLocation.scala:11)
//  at Code.main(ZipInputLocation.scala)

更新了第二个样本。

object Code {
  def main(args: Array[String]): Unit = {
    println(computeSomething("good"))
    println(computeSomething(null))
    def computeSomething(text: String): String = {
      require text != null
      //or
      //if(text == null)
      //  throw new RuntimeException("You broke the contract")
      "not null text was [" + text + "]"
    }
  }
}
//System.out:
//
//not null text was [good]
//Exception in thread "main" RuntimeException:
//  at Code$.computeSomething$1(ZipInputLocation.scala:13)
//  at Code$.main(ZipInputLocation.scala:11)
//  at Code.main(ZipInputLocation.scala)

2 个答案:

答案 0 :(得分:7)

不要使用Option.get。相反,请使用Option.applymap,因为它会为None值返回null

def computeSomething(text: String): Option[String] =
  Option(text).map("not null text was [" + _ + "]")

更好的是,如果您想禁止某人编译在编译时显式传递Some(null)的代码,请使用WartMover之类的工具,它具有生成编译时警告的特定规则。

答案 1 :(得分:3)

如果我理解正确,您希望Some(null)抛出异常,而不是将null存储为值,是否正确?

不幸的是,这不会发生。您唯一的选择是在函数中创建Some实例并明确检查null。例如:

def wrapSome(s: String): Some[String] = {
  if(s eq null) throw new NullPointerException("Can't have null string!")
  Some(s)
}

可能不是你想听的,也不是特别有用......

或者,您可以将值包装在Option中(如果值为None,则生成null),而不是Some中的值{ {1}}如果值为Some(null)),则调用null.get会抛出None.get。实际上,这正是您在示例中所做的。 (有没有理由为什么要使用NoSuchElementException显式包装值,而Some包含的非null值会自动包含该值?)

Option的主要目标之一是防范Option值。显然,它取决于您尝试实现的目标,但功能编程会阻止null值和抛出异常。如果你来自 Java ,起初看起来很奇怪。

更具功能性的方法是这样的:

null

使用这样的// Return None if s is null; otherwise, Some(s). Both are Option[String] values. def computeSomething(s: String): Option[String] = Option(s) // Use this function to create an optional string. val os = computeSomething(x) // x is some string. Could be null. // Provide a default value if wrapped value is null (i.e. if os is None). val a = os.getOrElse("some default value") // a is a string, never null. // Do something with the value if it's not null; do nothing otherwise. os.foreach(doSomething) // Calls doSomething(x), but only if x wasn't null/os isn't None. // Process the string to something else. If os is None, result is None too. val len = os.map(_.length) // Returns an Option[Int], None or Some(length of x) // etc. 值有很多习惯用语,其中没有一个涉及抛出异常。如果您可以告诉我们有关您尝试做什么的更多信息,我会向您展示 Scala / 功能的做法。

与此同时,这是使用Option方法使用此习惯用法的程序的重写版本:

fold