(快速參考)

13 靜態類型檢查和編譯

版本 6.2.0

13 靜態類型檢查和編譯

Groovy 是一種動態語言,預設情況下,Groovy 使用動態調用機制來執行方法呼叫和屬性存取。此動態調用機制為語言提供了極大的彈性和功能。例如,可以在執行階段動態新增方法至類別,也可以在執行階段動態取代現有的方法。此類功能非常重要,並為語言提供了極大的功能。不過,有時您可能想要停用此動態調用,而改用更靜態的調用機制,而 Groovy 提供了一種方法可以做到這一點。要告訴 Groovy 編譯器特定類別應該以靜態方式編譯,請使用 groovy.transform.CompileStatic 注解標記類別,如下所示。

import groovy.transform.CompileStatic

@CompileStatic
class MyClass {

    // this class will be statically compiled...

}

請參閱 這些關於 Groovy 靜態編譯的注意事項,以進一步瞭解 CompileStatic 的運作方式以及您可能想要使用它的原因。

使用 CompileStatic 的一個限制是,當你使用它時,你放棄了動態調用的功能和靈活性。例如,在 Grails 中,你將無法從標記為 CompileStatic 的類別呼叫 GORM 動態查找器,因為編譯器無法驗證動態查找器方法是否存在,因為它在編譯時不存在。你可能希望利用 Groovy 的靜態編譯優點,而不會放棄對 Grails 特定事項(例如動態查找器)的動態調用,這時 grails.compiler.GrailsCompileStatic 就派上用場了。GrailsCompileStatic 的行為就像 CompileStatic,但它知道某些 Grails 功能,並允許動態存取這些特定功能。

13.1 GrailsCompileStatic 標註

GrailsCompileStatic

GrailsCompileStatic 標註可以套用在類別或類別中的方法。

import grails.compiler.GrailsCompileStatic

@GrailsCompileStatic
class SomeClass {

    // all of the code in this class will be statically compiled

    def methodOne() {
        // ...
    }

    def methodTwo() {
        // ...
    }

    def methodThree() {
        // ...
    }
}
import grails.compiler.GrailsCompileStatic

class SomeClass {

    // methodOne and methodThree will be statically compiled
    // methodTwo will be dynamically compiled

    @GrailsCompileStatic
    def methodOne() {
        // ...
    }

    def methodTwo() {
        // ...
    }

    @GrailsCompileStatic
    def methodThree() {
        // ...
    }
}

可以透過標記 GrailsCompileStatic 並指定應略過特定方法的類型檢查,來標記一個類別並排除特定方法,如下所示。

import grails.compiler.GrailsCompileStatic
import groovy.transform.TypeCheckingMode

@GrailsCompileStatic
class SomeClass {

    // methodOne and methodThree will be statically compiled
    // methodTwo will be dynamically compiled

    def methodOne() {
        // ...
    }

    @GrailsCompileStatic(TypeCheckingMode.SKIP)
    def methodTwo() {
        // ...
    }

    def methodThree() {
        // ...
    }
}

標記為 GrailsCompileStatic 的程式碼都將靜態編譯,但 Grails 特定的互動除外,這些互動無法靜態編譯,但 GrailsCompileStatic 可以識別為允許動態調用。這些包括呼叫動態查找器和在組態區塊中的 DSL 程式碼,例如約束和網域類別中的對應封閉。

決定靜態編譯程式碼時必須小心。靜態編譯有一些好處,但為了利用這些好處,你放棄了動態調用的功能和靈活性。例如,如果程式碼是靜態編譯的,它就不能利用外掛程式可能提供的執行時期元程式設計增強功能。

13.2 GrailsTypeChecked 標註

GrailsTypeChecked

grails.compiler.GrailsTypeChecked 標註的工作方式很像 GrailsCompileStatic 標註,但它只啟用靜態類型檢查,而不是靜態編譯。這提供了編譯時間回饋,用於在編譯時無法靜態驗證的表達式,同時仍保留類別的動態調用。

import grails.compiler.GrailsTypeChecked

@GrailsTypeChecked
class SomeClass {

    // all of the code in this class will be statically type
    // checked and will be dynamically dispatched at runtime

    def methodOne() {
        // ...
    }

    def methodTwo() {
        // ...
    }

    def methodThree() {
        // ...
    }
}