12

我知道在 Scala 中,一个方法永远不应该返回null……但是输入参数呢?鉴于以下代码片段...

object MyObject {

    def myMethod(p: String): Option[String] = {
        if (p == null) throw new IllegalArgumentException("p is null.")
        ...
    }
}

...我检查的方式是否p正确?有什么建议吗?

4

4 回答 4

23

约定是 Scala 代码不使用空值(有少量异常,在使用这些库函数时应该立即修复)。

因此,Scala 中的 null 表示出现问题(至少是PBCAK),因此您不妨抛出异常。这不是常规操作;这是严重搞砸的事情。在遇到严重错误的地方捕获异常。捕捉 anIllegalArgumentException而不是 aNullPointerException不会增加额外的信息。只留下原件。

如果代码来自 Java,处理它的规范方法是将其包装在 中Option,这将转换nullNone. 那么你可能甚至不需要抛出异常;只返回一个None.

def myMethod(p: String) = Option(p).map(_.toLowerCase)

如果您在它为空时无法继续,那么您需要考虑信息异常是否会有所帮助。 Option(p).orElse(throw new IllegalArgumentException("Null!"))是表达异常抛出情绪的一种紧凑方式。

在 Scala 2.10 中,您还可以包装一些东西,scala.util.Try(...)这些东西会自动为您捕获和打包异常。如果您想要一个打包的异常而不是抛出一个异常,这就是要走的路。(并使用Try而不是Option。)

import scala.util.Try
def myMethod(p: String) = Try(p.toLowerCase)

最后,对于替代结果的更一般处理,请使用Either. 错误处理的约定是预期的输出是 a Right(whatever),而Left(whatever)表示出现了问题。

于 2012-11-29T22:49:28.257 回答
6

有几种方法,你的方法是一种。

您还可以使用:

require(p != null, "p is null.")

或者“更实用”的方式是使用Option

def myMethod(p: String): Option[String] = {

  // no exception
  for {
    pp <- Option(p)
  } yield p + " foo bar"
}

编辑:

或者,如果您希望没有抛出异常的错误,您可以使用Either

def myMethod(p: String): Either[Exception, String] = {
  if(p == null) Left(new IllegalArgumentException("p is null."))
  else Right(p + "foo bar")
}
于 2012-11-29T22:07:11.350 回答
0

Scala 习语本质上是“永远不要使用空值”。因此,除非您正在编写一个需要适应肮脏的 Java 用户的 API,否则我不会担心它。否则,您将最终为您编写的每个方法的每个参数插入此样板检查。

你漂亮的单行方法

def square(x: String): String = math.pow(x.toInt, 2).toInt.toString

会变成一些尴尬的东西

def square(x: String): String = 
    if (x == null) throw new NullPointerException()
    math.pow(x.toInt, 2).toInt.toString
}

或者

def square(x: String): String = Option(x) match {
    case Some(x) => math.pow(x.toInt, 2).toInt.toString
    case None => throw new NullPointerException()
}

多么可怕。

于 2012-11-29T22:29:15.770 回答
0

我最喜欢的方法是:

object HandlingInputValidation {

  def main(args: Array[String]) = {
    println("A1: " + handleInput("Correct ") + " END")
    println("A2: " + handleInput("Correct") + " END")
    println("A3: " + handleInput("") + " END")
    println("A4: " + handleInput(" ") + " END")
    println("A5: " + handleInput(null) + " END")
  }

  def handleInput(data: String): Option[String] = {
    Option(data).map(_.trim.toLowerCase)
  }
 }

在这种情况下,nullwill be None,并且空格将被修剪。

于 2017-12-12T15:54:16.990 回答