2016-11-10 73 views
2

有時,使用import語句來訪問對象的多個元素會更方便和更清晰。在scala中代碼塊導入昂貴

例如,代碼

x.y.z.a = 1 
x.y.z.b = 2 
x.y.z.c = 3 

可以寫成

{ 
    import x.y.z._ 

    a = 1 
    b = 2 
    c = 3 
} 

顯然是有用得多,當名稱是更長的時間。

所有的工作是在編譯時完成的,還是以某種方式在運行時執行的導入語句?使用這種風格有沒有效率或其他方面的成本?

回答

4

是的,所有的名字和含義都是在編譯時解決的,import不影響其他任何東西。

當然,什麼得到執行的仍然是

x.y.z.a = 1 
x.y.z.b = 2 
x.y.z.c = 3 

所以你獲取(在這個例子中)x.y.z 3倍。如果z

package x.y 
object z { ... } 

這再次只是名稱解析;但相反,如果你碰到這樣的

object x { 
    val y = ... // some type which has val z 
} 

這2方法調用每個時間和投入z到一個局部變量進行更好的(但如果這個代碼的運行往往不夠JIT可以優化這一點)。

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" 
    } 
} 

編譯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 
     ... 

字面上相同的字節碼。