Kotlin進階知識(十二)——聲明並應用註解

1、應用註解

在Kotlin中使用註解的方法和Java同樣。要應用一個註解,以**@字符做爲(註解)名字的前綴**,並放在要註解的聲明最前面git

註解只能擁有以下類型的參數:基本數據類型字符串枚舉類引用其餘的註解類,以及前面這些類型數組github

指定註解實參的語法與Java有些微小的差異:json

  • 要把一個類指定爲註解實參,在類名後加上**::class: @MyAnnotation(MyClass::class)**。
  • 要把另外一個註解指定爲一個實參去掉註解名稱前面的@
  • 要把一個數組指定爲一個實參,使用**arrayOf函數**:@RequestMapping(path = arrayOf("/foo", "/bar"))

註解實參須要在編譯期就是已知的,因此不能引用任意的屬性做爲實參。要把屬性看成註解實參使用,須要用**const修飾符標記它,來告知編譯器這個屬性編譯期變量**。數組

const val TEST_TIMEOUT = 100L

@Test(timeout = TEST_TIMEOUT) fun testMethod() { ... }
複製代碼

2、註解目標

使用點目標聲明被用來說明要註解的元素。使用點目標被放在**@符號註解名稱之間,並用冒號和註解名稱隔開**,如圖1。markdown

圖1:說明使用點目標的語法

class HasTempFolder {
    // 註解的是getter,而不是屬性。
    @get: Rule
    val folder = TemporaryFolder()

    @Test
    fun testUsingTempFolder() {
        // ...
    }
}
複製代碼

注:上述代碼需使用JUnit框架app

使用Java中聲明的註解來註解一個屬性,它會被默認地應用到相應的字段上。Kotlin也可讓你聲明被直接對應到屬性上的註解。框架

Kotlin支持的使用點目標的完整列表以下:函數

  • property:Java的註解不能應用這種使用點目標。
  • field:爲屬性生成的字段
  • get:屬性的getter
  • set: 屬性的setter
  • receiver擴展函數或者擴展屬性接受者參數
  • param構造方法的參數
  • setparam: **屬性setter**的參數
  • delegate: 爲委託屬性存儲委託實例的字段
  • file: 包含在文件中聲明的頂層函數和屬性的類

注意:任何應用到file目標的註解都必須放在文件的頂層,放在**package指令以前**。oop

用註解控制JavaAPI Kotlin提供了各類註解來控制Kotlin編寫的聲明如何編譯成字節碼並暴露給Java調用者。spa

  • @JvmName 將改變由**Kotlin生成的Java方法或字段的名稱**
  • @JvmStatic 能被用在對象聲明或者伴生對象方法上,把它們暴露成**Java的靜態方法**
  • @JvmOverloads 指導Kotlin編譯器爲帶默認參數值的函數生成多個重載(函數)
  • @JvmField 能夠應用於一個屬性,把這個屬性暴露成一個沒有訪問器的公有Java字段

3、聲明註解

annotation class JsonExclude
複製代碼

語法看起來和常規類的聲明很像,只是在class關鍵字以前加上了**annotation修飾符**。由於註解類只是用來定義關聯到聲明和表達式元數據的結構,它們不能包含**任何代碼**。所以編譯器禁止爲一個註解類指定類主體。

4、元註解:控制如何處理一個註解

和Java同樣,一個Kotlin註解類本身也能夠被註解。能夠應用到註解類上的註解被稱做元註解。

標準庫定義的元註解中最多見的就是@Target。JKid中@JsonExclude和@JsonName的聲明使用它爲這些註解指定有效的目標。

@Target(AnnotationTarget.PRIPERTY)
annotation class JsonExclude
複製代碼

注:@JsonExclude 是 JKid庫中的方法

@Target元註解說明了註解能夠被應用的元素類型。若是不使用它全部的聲明均可以應用這個註解。這並非JKid想要的,由於它只須要處理屬性的註解。

5、使用泛型類作註解參數

@CustomSerializer註解接受一個自定義序列化器類的引用做爲實參

interface ValueSerializer<T> {
    fun toJsonValue(value: T): Any?
    fun fromJsonValue(jsonValue: Any?): T
}

data class PersonAnnotation(
    val name: String,
    @CustomSerializer(DateSerializer::class) val birthDate: Date
)

// @CustomSerializer底層源碼
annotation class CustomSerializer(
    val serializerClass: KClass<out ValueSerializer<*>>
)
複製代碼
相關文章
相關標籤/搜索