Kotlin注解

Annotations | Kotlin (kotlinlang.org)

是什么?

附加到代码的元数据。

声明注解

声明方式

在类前添加 annotation修饰符

annotation class Fancy

指定额外属性:

  • @Target: 目标元素类型
  • @Retention: 存储类型
  • @Repeatable:单个元素上是否可以应用多个
  • @MustBeDocumented: 标记注解是公开API的一部分,会被包含到生成的公开的API文档中。
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
        AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER,
        AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy

构造

可以添加构造参数

annotation class Special(val why: String)

@Special("example") class Foo {}

参数类型:

  • Java原始类型对应的类型
  • Strings
  • Classes(Foo::class)
    • 指定类作为参数时,可以使用Kotlin类(KClass),编译器会自动将其转换为Java类
  • Enums
  • 其他注解
    • 注解类型用作参数时,无需使用 @前缀。
  • 上述类型的数组类型

实例化

在Java中,注解类型是接口的形式,因此可以实现注解接口并且使用其实例。

在Kotlin中,可以调用注解

使用

一般用法:
@Fancy class Foo {
    @Fancy fun baz(@Fancy foo: Int): Int {
        return (@Fancy 1)
    }
}

主构造函数注解需要添加 constructor 关键字

class Foo @Inject constructor(dependency: MyDependency) { ... }

属性访问器也可以被注解:

class Foo {
    var x: MyDependency? = null
        @Inject set
}

lambdas 表达式也可以被注解:注解会被应用到lambda表达式生成的 invoke() 方法上

annotation class Suspendable

val f = @Suspendable { Fiber.sleep(10) }
use-site target 注解

当注解一个属性或者构造函数参数时,由于该属性可能会生成多个java对应的元素,如属性,get和set方法,所以注解在java字节码中有多个可能的位置,使用如下格式可以精确的指定位置:

class Example(@field:Ann val foo,    // annotate Java field
              @get:Ann val bar,      // annotate Java getter
              @param:Ann val quux)   // annotate Java constructor parameter

添加到整个文件的注解:(在package导入之前)

@file:JvmName("Foo")

package org.jetbrains.demo

单个元素上多个注解的合并写法:

class Example {
     @set:[Inject VisibleForTesting]
     var collaborator: Collaborator
}

支持的use-site target:

  • file

  • property (使用此标记的注解目标对java不可见)

  • field

  • get (property getter)

  • set (property setter)

  • receiver (扩展函数的receiver 参数或者属性)

    • 注解扩展函数的receiver的参数用法:

      • fun @receiver:Fancy String.myExtension() { ... }
        
  • param (构造函数参数)

  • setparam (属性 setter parameter)

  • delegate (the field storing the delegate instance for a delegated property)

没有指定target时的默认顺序:

  • param
  • property
  • field

Java注解

Java注解百分百兼容Kotlin。

参数顺序

由于java注解中的参数顺序是未定义的,所以不能使用正常的函数参数调用格式来传递参数,需要使用命名参数的格式:

// Java
public @interface Ann {
    int intValue();
    String stringValue();
}
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C

value参数省略名称

Java中, 名为value的参数可以省略名称,kotlin也支持。

// Java
public @interface AnnWithValue {
    String value();
}

// Kotlin
@AnnWithValue("abc") class C

数组作为注解参数

java中的value注解参数如果是数组类型,那么在kotlin中会作为 vararg 参数

// Java
public @interface AnnWithArrayValue {
    String[] value();
}
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C

名称不是value的参数则需要使用数组字面量格式,或者使用arrayOf(...)

// Java
public @interface AnnWithArrayMethod {
    String[] names();
}
@AnnWithArrayMethod(names = ["abc", "foo", "bar"])
class C

访问注解实例的属性

java注解实例的value在kotlin中表现为属性形式,可通过如下方式来访问

// Java
public @interface Ann {
    int value();
}
// Kotlin
fun foo(ann: Ann) {
    val i = ann.value
}

可重复注解

Kotlin也拥有java一样的可在一个元素上应用多次的可重复注解。

声明为可重复注解

通过 @kotlin.annotation.Repeatable 元注解标记注解即可。被标记的 注解在java及kotlin侧都将是可重复的

差异

Java 不支持 containing 注解。

Kotlin 编译器会自动生成一个预定义名称的containing注解,如:

@Repeatable
annotation class Tag(val name: String)

// 编译器自动生成名为 @Tag.Container 的 containing 注解

自定义名称:通过应用@kotlin.jvm.JvmRepeatable 元注解并传递一个包含注解作为参数的注解可以自定义containing注解的名称

@JvmRepeatable(Tags::class)
annotation class Tag(val name: String)

annotation class Tags(val value: Array<Tag>)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值