Scala 案例类命名参数是否具有一定的性能成本



我发现在我的项目中使用它非常方便:

case class Thing(a: Option[String], b: Option[String], c: Option[String])
...
val a = Thing(a = Some("A"))
val b = Thing(b = Some("B"))
val c = Thing(b = Some("B"), c = Some("C"))

它实际上减少了很多丑陋的 None 定义并且看起来更具可读性,但现在我想知道这个和那个在性能/实现方面有什么区别吗?

val a = Thing(Some("A"), None, None)
val b = Thing(None, Some("B"), None)
val c = Thing(None, Some("B"), Some("C"))

谢谢

从语义上讲,没有区别,因为None是一个单例对象。但是,在性能方面,我们可以看到在后台生成了哪种代码。

case class Thing(
  a: Option[String] = None,
  b: Option[String] = None,
  c: Option[String] = None
)
object Thing {
  def foo() = {
    val a1 = Thing(a = Some("A"))
    val b1 = Thing(b = Some("B"))
    val c1 = Thing(b = Some("B"), c = Some("C"))
    val a2 = Thing(Some("A"), None, None)
    val b2 = Thing(None, Some("B"), None)
    val c2 = Thing(None, Some("B"), Some("C"))
  }
}

我相信这是你问的那种事情的一个例子。我们可以用scalac Thing.java -Xprint:jvm来编译它,看看 Scala 编译器在去除所有语法糖后还剩下什么。

val a1: Thing = new Thing(new Some("A"), Thing.apply$default$2(), Thing.apply$default$3());
val b1: Thing = {
  <artifact> val x$1: Some = new Some("B");
  <artifact> val x$2: Option = Thing.apply$default$1();
  <artifact> val x$3: Option = Thing.apply$default$3();
  new Thing(x$2, x$1, x$3)
};
val c1: Thing = {
  <artifact> val x$4: Some = new Some("B");
  <artifact> val x$5: Some = new Some("C");
  <artifact> val x$6: Option = Thing.apply$default$1();
  new Thing(x$6, x$4, x$5)
};
val a2: Thing = new Thing(new Some("A"), scala.None, scala.None);
val b2: Thing = new Thing(scala.None, new Some("B"), scala.None);
val c2: Thing = new Thing(scala.None, new Some("B"), new Some("C"));

因此,使用命名语法可以引入一些中间变量。但函数调用本质上是模数字节的堆栈空间。更有可能的是,JIT 会将它们编译为性能类似的代码片段,所以我会说你没有什么可担心的。

最新更新