深入kotlin - 枚举和注解

Posted 颐和园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入kotlin - 枚举和注解相关的知识,希望对你有一定的参考价值。

枚举

所谓枚举,就是实例个数有限的类。

定义

enum class Season 
	SPRING, SUMMER, AUTUMN, WINTER

既然是class,当然也可以有主构造器,通过主构造器为所有实例的 temperature 赋予不同的初始值:

enum class Season2(val temperature: Int) 
  SPRING(10), SUMMER(30),AUTUMN(30),WINTER(0)

当然也可以声明方法,而且可以在实例中重写方法:

enum class Season3 
	SPRING  // 1
		override fun getSeason():Season3 = SPRING
	
  ......
  ; // 2
	abstract fun getSeason(): Season3 //3

  1. 重写枚举的抽象方法。
  2. 分号不可省略,用于分隔枚举的实例定义和方法定义。
  3. 枚举允许定义方法。

实例化

kotlin 的枚举基本上跟 java 一样,需要通过实例进行使用:

var seasons = Season.values() // 获取 Season 中全部实例
seasons.forEach println(it)  // 打印:SPRING SUMMER AUTUMN WINTER
val season = Season.valueOf("SPRING") // 通过字符串(即枚举对象的 name)获得对应的枚举实例(即 SPRING)
println(season.name) // 打印:SPRING

注解

在 java 中使用 @Interface 可以定义注解。在 kotlin 中,使用 annotation class 定义注解:

annotation class MyAnnotation

元注解

元注解是修饰注解的注解,通常在定义注解时使用。

@Target

用于表示该注解可以应用于什么样的对象上,比如 CLASS、ANNOTATION_CLASS、PROPERTY、FIELD :

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.EXPRESSION, AnnotationTarget.VALUE_PARAMETER)
annotation class MyAnnotation
@Retention

用于注解的保存方式,有3个可能值:

  • SOURCE 表示源代码,当编译以后注解就不存在了。
  • BINARY 表示二进制。
  • RUNTIME 表示运行时。
@Retention(AnnotationRetention.SOURCE)
annotation class MyAnnotation
@MustBeDocumented

表示该注解应该包含在所生成的文档中。

@MustBeDocumented
annotation class MyAnnotation

使用注解

在指定的 target 上使用即可。

@MyAnnotation // @Target 中包括 AnnotationTarget.CLASS
class MyClass 
  @MyAnnotation // @Target 中包括 AnnotationTarget.FUNCTION
  fun method(@MyAnnotation a: Int):Int  // @Target 中包括 AnnotationTarget.VALUE_PARAMETER(方法参数)
    return (@MyAnnotation 10) // @Target 中包括AnnotationTarget.EXPRESSION 
  

在主构造器上使用注解

在主构造器上使用注解时,constructor 关键字不可省略:

class MyClass @MyAnnotation constructor(a: Int) 
在 set 方法上使用注解

同样在 set 方法上使用注解时,set 关键字不可省略:

class MyClass 
	var a: Int? = null
		@MyAnnotation set // @Target 中包括 AnnotationTarget.PROPERTY_SETTER

注解的构造器

注解也可以定义构造方法及构造参数。构造参数所允许的类型包括:

  • 8 种原生类型: Int, Long …
  • String
  • Class 类型(MyClass::class)
  • 枚举
  • 其他的注解
  • 上述类型的数组
annotation class MyAnnotation(val str: String)
@MyAnnotation("hello")
class MyClass

annotation class MyAnnotation2(val str: String, val myAnnotation: MyAnnotation) // 1 
@MyAnnotation2("test", MyAnnotation("welcome")) // 2
class MyClass2
  1. MyAnnotation2 的第二个构造参数是另外一个注解 MyAnnotation
  2. 使用 MyAnnotation2 时,第二个参数传入一个 MyAnnotation 实例

此外,注解参数不支持 optional,因为 JVM 不支持 null 形式存储注解的属性值,如果某个注解被用作其他注解的构造参数,那么其名字不需要以 @ 开头(见 1)。

如果注解构造参数使用 class 类型,那么要使用 kotlin 的 class(KClass) 而非 java class,kotlin 编译器会自动将其转换为 java class。

annotation class MyAnnotation(val arg1: KClass<*>, val arg2: KClass<out Any>)
@MyAnnotaion(String::class, Int::class)
class MyClass

KClass 位于 kotlin.reflect 包下,如果 IDE 不能自动导入,请手工导入。

注解使用处目标

在类的属性或者主构造参数上使用注解时,会存在多个 java 元素都可以通过对应的 kotlin 元素生成出来。因此在字节码中,会有多处位置生成注解,如果要指定具体的注解生成位置,可以通过“使用处目标“来避免这种歧义。

class MyClass(@field: MyAnnotation val arg1: String, // 1
              @get: MyAnnotation val arg2: String, // 2
              @param: MyAnnotation val arg3: String) // 3

  1. 生成注解时,在 java field 级别生成。
  2. 在 java get 方法上生成注解。
  3. 在 java 构造方法的参数处生成注解。

还可以在文件级别生成注解,此时注解位于文件第一行:

@file: JvmName("HelloKotlin") // 用指定文件名作为最终生成的字节码文件名,覆盖默认的文件名
package com.sample.kotlinstudy
import .....

Java 注解与 kotlin 注解兼容

二者是完全兼容的。

以上是关于深入kotlin - 枚举和注解的主要内容,如果未能解决你的问题,请参考以下文章

深入kotlin - 基础语法

深入kotlin - 基础语法

从零开始学Kotlin-枚举

Kotlin 枚举类

kotlin 中的重载分辨率歧义错误

将 graphql 枚举映射到 kotlin 枚举