scala中的代码块导入内部代价高昂

Luc*_*cas 2 performance scala

有时使用import语句来访问对象的多个元素是方便和清晰的.

例如,代码

x.y.z.a = 1
x.y.z.b = 2
x.y.z.c = 3
Run Code Online (Sandbox Code Playgroud)

可写成

{
    import x.y.z._

    a = 1
    b = 2
    c = 3
}
Run Code Online (Sandbox Code Playgroud)

显然,当名字更长时,它会更有用.

所有工作都是在编译时完成的,还是以某种方式在运行时执行import语句?使用这种风格是否有任何成本,效率或其他方面的成本?

Ale*_*nov 5

是的,所有名称和隐式都在编译时解析,并且import不会影响其他任何内容。

当然,执行的仍然是

x.y.z.a = 1
x.y.z.b = 2
x.y.z.c = 3
Run Code Online (Sandbox Code Playgroud)

所以你会获取x.y.z3 次(在本例中)。如果z

package x.y
object z { ... }
Run Code Online (Sandbox Code Playgroud)

这又只是名称解析;但如果你有类似的东西

object x {
  val y = ... // some type which has val z
}
Run Code Online (Sandbox Code Playgroud)

每次调用 2 个方法,并将其放入z局部变量中效果更好(但如果此代码运行得足够频繁,JIT 可能会对此进行优化)。


Tra*_*own 5

你可以自己检查一下javap.从这样的事情开始:

package x.y {
  object z {
    var a = "abc"
    var b = "def"
    var c = "ghi"
  }
}

object Test {
  def withImport: Unit = {
    import x.y.z._

    a = "zyx"
    b = "wvu"
    c = "rst"
  }

  def withoutImport: Unit = {
    x.y.z.a = "zyx"
    x.y.z.b = "wvu"
    x.y.z.c = "rst"
  }
}
Run Code Online (Sandbox Code Playgroud)

编译scalac Test.scala然后javap -c Test\$:

  public void withImport();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
         3: ldc           #20                 // String zyx
         5: invokevirtual #24                 // Method x/y/z$.a_$eq:(Ljava/lang/String;)V
         8: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
        11: ldc           #26                 // String wvu
        13: invokevirtual #29                 // Method x/y/z$.b_$eq:(Ljava/lang/String;)V
        16: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
        19: ldc           #31                 // String rst
        21: invokevirtual #34                 // Method x/y/z$.c_$eq:(Ljava/lang/String;)V
        24: return
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  this   LTest$;
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 15: 16

  public void withoutImport();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
         3: ldc           #20                 // String zyx
         5: invokevirtual #24                 // Method x/y/z$.a_$eq:(Ljava/lang/String;)V
         8: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
        11: ldc           #26                 // String wvu
        13: invokevirtual #29                 // Method x/y/z$.b_$eq:(Ljava/lang/String;)V
        16: getstatic     #18                 // Field x/y/z$.MODULE$:Lx/y/z$;
        19: ldc           #31                 // String rst
        21: invokevirtual #34                 // Method x/y/z$.c_$eq:(Ljava/lang/String;)V
        24: return
        ...
Run Code Online (Sandbox Code Playgroud)

字面上相同的字节码.