使用Any vs特定参数类型是否有任何陷阱?

时间:2015-04-26 13:42:08

标签: scala types arguments

假设我想要一个方法来输出某些东西,在这种情况下是一个字符串或整数。我可以这样做:

def outString(str: String) {
    str // or "return str"
}

并按照以下方式运行:outString("foo")

但是我也可以避免将特定类型初始化为参数并且它可以工作:

def outString(str: Any) {
    str
}

并按以下方式运行:outString("foo")outString(123)

鉴于他们都工作并假设你不总是知道所传递的参数的类型,使用Any对特定参数类型有任何陷阱吗? Any是否进行任何类型的自动类型检查,如解释语言会降低代码速度?

1 个答案:

答案 0 :(得分:6)

在运行时性能等方面,以下两种方法没有实际区别:

def genericLog[A](a: A): Unit = println(a.toString)
def anyLog(a: Any): Unit = println(a.toString)

只要你只使用Any上的方法,而不是使用isInstanceOfasInstanceOf或模式匹配执行运行时类型检查或强制转换,就会有&#39>没有性能影响。

问题是there aren't many things you can do with Any,你可以做的事情(检查相等性和转换为字符串)并不是非常有用(例如,尝试打印数组)。一旦你需要写这样的东西:

def anyLog(a: Any): Unit = a match {
  case i: Int => println("Int: " + i)
  case s: String => println("String: " + s)
  case other => println("Other: " + other)
}

您回到了运行时类型检查的范围内,这确实会对性能产生影响,但更重要的是会破坏您和其他人推理代码的能力。

所以是的,如果你绝对确定除了致电toString之外你永远不需要做任何事情,你可以在这里使用Any。如果您正在撰写惯用的Scala代码,这种情况不会经常出现,我个人建议明确地避免Any 无处不在,包括像这样的情况。

更新:正如@pedrofurla在下面的评论中指出的那样,采用Int参数的方法与采用Any的方法之间存在一个重要区别。在Any - take方法中,整数参数将被加框,而它在({1}} - 采用方法中不一定(必然)。

非常非常容易在Scala(Int1.toString中意外地装箱原语,例如),并且通常它可能不会你应该担心的事情,直到基准测试或分析器告诉你它在特定情况下是一个问题。但这是避免println(1)参数的另一个原因,因为非泛型Any参数或带Int注释的泛型参数都不会导致不必要的装箱。< / p>