Detailed explanations and examples of Kotlin's annotation class
Annotation statement
Annotations are methods of appending metadata to code. To declare annotation, place the annotation modifier in front of the class:
annotation class Fancy
Additional attributes of annotations can be specified by annotating the annotation class with meta annotations:
- @Target Specifies possible types (classes, functions, attributes, expressions, etc.) of elements that can be annotated with this annotation;
- @Retention Specifies whether the annotation is stored in the compiled class file and whether it can be visible through reflection at runtime (the default is true);
- @Repeatable allows the same annotation to be used multiple times on a single element;
- @MustBeDocumented Specifies that the annotation is part of the public API and should be included in the signature of the class or method displayed in the generated API document.
@Target(, ,
AnnotationTarget.VALUE_PARAMETER, )
@Retention()
@MustBeDocumented
annotation class Fancy
usage
@Fancy class Foo { @Fancy fun baz(@Fancy foo: Int): Int { return (@Fancy 1) } }
If you need to annotate the main constructor of a class, you need to add the constructor keyword in the constructor declaration and add the annotation to its front:
class Foo @Inject constructor(dependency: MyDependency) { // …… }
You can also label the property accessor:
class Foo { var x: MyDependency? = null @Inject set }
Constructor
Annotations can have constructors that accept parameters.
annotation class Special(val why: String) @Special("example") class Foo {}
The allowed parameter types are:
- Types corresponding to Java native types (Int, Long, etc.);
- string;
- class (Foo::class);
- enumerate;
- Other notes;
- Array of type columned above.
Annotation parameters cannot have null types because the JVM does not support storing null as the value of the annotation property.
If the annotation is used as a parameter to another annotation, its name is not prefixed with the @ character:
annotation class ReplaceWith(val expression: String) annotation class Deprecated( val message: String, val replaceWith: ReplaceWith = ReplaceWith("")) @Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
If you need to specify a class as an annotation parameter, use the Kotlin class (KClass). The Kotlin compiler will automatically convert it to a Java class so that the Java code can see the annotation and parameters normally.
import annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>) @Ann(String::class, Int::class) class MyClass
Lambda expressions
Annotations can also be used in lambda expressions. They are applied to the invoke() method that generates the lambda expression body. This is useful for frameworks like Quasar, which uses annotations for concurrent control.
annotation class Suspendable val f = @Suspendable { (10) }
Annotation usage target
When annotating attributes or main constructor parameters, there will be multiple Java elements generated from the corresponding Kotlin element, so there are multiple possible locations for this annotation in the generated Java bytecode. If you want to specify exactly how the annotation should be generated, use the following syntax:
class Example(@field:Ann val foo, // Tag Java fields @get:Ann val bar, // Tag Java getter @param:Ann val quux) // Annotate Java constructor parameters
The same syntax can be used to label the entire file. To do this, place the annotation with the target file at the top level of the file, before the package directive, or before all imports (if the file is in the default package):
@file:JvmName("Foo") package
If you have multiple annotations for the same target, you can avoid duplication of the target by adding square brackets after the target and putting all annotations in square brackets:
class Example { @set:[Inject VisibleForTesting] var collaborator: Collaborator }
The complete list of supported usage targets is:
- file
- property (annotations with this target are not visible to Java)
- field
- get (property getter)
- set (property setter)
- receiver (receiver parameter of extended function or attribute)
- param (constructor parameter)
- setparam (property setter parameter)
- delegate (the field that stores its delegate instance for the delegate attribute)
To annotate the receiver parameters of the extension function, use the following syntax:
fun @receiver:Fancy () { }
If the target is not specified, the target is selected based on the @Target annotation of the annotation being used. If there are multiple applicable targets, use the first applicable target in the following list:
- param
- property
- field
Java Annotations
Java annotations are 100% compatible with Kotlin:
import import .* import import .* class Tests { // Apply the @Rule annotation to the property getter @get:Rule val tempFolder = TemporaryFolder() @Test fun simple() { val f = () assertEquals(42, getTheAnswer()) } }
Because Java-written annotations do not define the parameter order, the parameters cannot be passed using regular function call syntax. Instead, you need to use named parameter syntax.
// Java public @interface Ann { int intValue(); String stringValue(); } // Kotlin @Ann(intValue = 1, stringValue = "abc") class C
Just like in Java, a special case is the value parameter; its value does not need to be specified explicitly.
// Java public @interface AnnWithValue { String value(); } // Kotlin @AnnWithValue("abc") class C
If the value parameter in Java has an array type, it becomes a vararg parameter in Kotlin:
// Java public @interface AnnWithArrayValue { String[] value(); } // Kotlin @AnnWithArrayValue("abc", "foo", "bar") class C
For other parameters with array type, you need to explicitly use arrayOf:
// Java public @interface AnnWithArrayMethod { String[] names(); } // Kotlin @AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar")) class C
The value of the annotated instance is exposed to the Kotlin code as an attribute.
// Java public @interface Ann { int value(); } // Kotlin fun foo(ann: Ann) { val i = }
Thank you for reading, I hope it can help you. Thank you for your support for this site!