Kotlin Annotations
Kotlin annotations
Annotations are used to attach metadata to classes, interfaces, parameters, and other elements at compile time. Annotations can be used by the compiler and reflected at runtime. Depending on annotation values, the meaning of data or a program can be changed.
Kotlin meta-annotations
You can add meta information when declaring an annotation. The following are some common meta-annotations:
| Annotation name | Usage |
|---|---|
@Target |
Specifies the kinds of elements to which the annotation can be applied. For example, it can specify that the annotation may be applied to classes, functions, properties, and so on. |
@Retention |
Specifies how long the annotation is retained. Kotlin provides three retention policies: SOURCE, BINARY, and RUNTIME. SOURCE is discarded after compilation, BINARY is included in the compiled class file but cannot be used at runtime, and RUNTIME is available at runtime. |
@Repeatable |
Allows the same annotation to be applied to the same element multiple times. It is supported starting with Kotlin 1.4. |
@MustBeDocumented |
Indicates that the annotation must be documented. In other words, when this annotation is used, it must appear in documentation. |
Annotation example
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class MyAnnotation
Creating annotations
To create an annotation, write the annotation modifier before the class.
annotation class MyAnnotation
Declaring an annotation on a constructor
You can also specify an annotation on a class constructor. Add the constructor keyword to the constructor declaration and write the annotation before it.
In Kotlin, declaring an annotation on a constructor is mainly applied to the primary constructor. The following is an example of declaring an annotation on a constructor:
class MyClass @Inject constructor() {
// class body
}
In the example above, the @Inject annotation is applied to the class constructor. In this case, the primary constructor of MyClass is handled with the @Inject annotation.
You can also use annotations on constructor parameters:
class MyClass {
constructor(@SomeAnnotation parameter: String) {
// constructor body
}
}
In the example above, the @SomeAnnotation annotation is applied to the parameter parameter.
Declaring an accessor annotation for a property
class MyClass{
var parameter: String? = null
@Inject set
}
Using a constructor when creating an annotation
You can also use a constructor when creating an annotation. To use a constructor as an annotation, parameters are required.
annotation class MyClass(val parameter: String)
@MyClass("parameter")
class Foo {
// ...
}
Parameters used in annotations cannot be nullable types. This is because the JVM does not support null as a value for annotation properties.
Also, one annotation can be used as a parameter of another annotation, but in this case the @ prefix should not be added:
annotation class ReplaceWith(val expression: String)
annotation class Deprecated(
val message: String,
val replaceWith: ReplaceWith = ReplaceWith(""), // @ is not added.
)
@Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
class Foo2 {
// ...
}
Also, when Kotlin’s KClass is used to specify a class as an annotation parameter, the Kotlin compiler automatically converts it to a Java class so that annotations and arguments can be seen normally.
import kotlin.reflect.KClass
annotation class MyClass(val arg1: KClass<*>, val arg2: KClass<out Any>)
@MyClass(String::class, Int::class)
class Foo
Using TYPE annotations
Create the Java annotation interface Ann.java:
package basic.annotations.ex5;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Ann {
int value();
}
Create a MyClass.kt class that uses the Ann annotation interface.
@Ann(value = 10)
class MyClass {
// ...
}
fun main(args: Array<String>) {
val clazz = MyClass()
val x = clazz.javaClass.getAnnotation(Ann::class.java)
if (x != null) {
println("Value:" + x?.value)
}
}
Output:
Value: 10