Kotlin - Annotations and Reflection

Kotlin annotations are used to attach metadata to classes, interface, parameters at compile time. In this article, you will learn about the Annotations and Reflection in Kotlin.

Introduction

 
In this part, we are going to learn about annotations and reflection in Kotlin language. Those who new to Kotlin and willing to learn, go through this article series: Introduction to Kotlin.
 

Kotlin Annotations

 
Kotlin annotations are used to attach metadata to classes, interfaces, parameters at compile time. Annotations are used by the compiler and the metadata is reflected at runtime using reflection.
 

Kotlin Meta-annotations

 
We can add meta-info while declaring annotations in our code. Following are some of the meta-annotations:
  • @Target - It targets all possible kinds of elements to be annotated with the annotation.
  • @Retention - It specifies the annotation is stored in the compiled class files or it is visible through reflection at run time.
  • @Repeatable - This meta-annotation determines that twice or more on a single code element.
  • @MustBeDocumented - This meta-document specifies that the part of the public API and it must be included in the class or method.
Here is an example of using annotations:
  1. @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,      
  2. AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)      
  3. @Retention(AnnotationRetention.SOURCE)      
  4. @MustBeDocumented      
  5. annotation class MyClass     

Declaring an annotation

 
Annotation is declared by placing the annotation keyword in front of a class. Once declared, the annotations are adding using the above defined meta-info tags. The followig code snippet declares a class with annotation and later meta-info is added to the class members.
  1. annotation class MyClass  
Here is an example of use of annotation in a working sample.
  1. import java.lang.annotation.ElementType;      
  2. import java.lang.annotation.Retention;      
  3. import java.lang.annotation.RetentionPolicy;      
  4. import java.lang.annotation.Target;      
  5. @Target(ElementType.TYPE)      
  6. @Retention(RetentionPolicy.RUNTIME)      
  7. @interface Ann{      
  8.    int value();      
  9.    }      
  10.    @Ann(value = 25)      
  11.    class MyClass{      
  12. }      
  13. fun main (args: Array<String>){      
  14.    var c = MyClass()      
  15.    var x = c.javaClass.getAnnotation(Ann::class.java)      
  16.    if(x!=null){      
  17.       println("Value:"+x?.value)      
  18.    }      
  19. }   
The output is:
 
Value: 25
 

Kotlin Reflection

 
Reflection in Kotlin allows program to read back the properties of a objects (class, interfaces etc) and libraries and read its meta data to learn about it. For example, you can read all classes in a library or all methods and properties of a class at runtime using reflection. Keep in mind, use of reflection is not common and it may affect the performance of the code.
 
Class Reference
 
The most common use of reflection is to get a class reference that returns a reference to the K class (KClass). We mist use the class literal (i.e. use double colons) for this.
 
Here is the syntax of class references that returns a val. 
  1. val c1 = String::class      
  2. val c2 = MyClass::class    

Functional Reference

 
Kotlin functional is used for the reference of function using double colons. The reference of function can be used as a parameter. To use this reference, we use the :: operator.
 
Example
  1. fun main(args: Array<String>) {      
  2.    fun isPositive(x: Int) = x > 0      
  3.    val numbers = listOf(-10, -5, 0, 5, 10)      
  4.    println(numbers.filter(::isPositive))      
  5. }    
Output
 
[5,10]
 

Overloaded function reference operator (::)

 
The operator :: can be used with an overloaded function when the type is known from the context.
 
Example
  1. fun main(args: Array<String>) {      
  2.    fun isPositive(x: Int) = x > 0      
  3.    fun isPositive(s: String)      
  4.    val numbers = listOf(-10,-5,0,6,12)      
  5.    val strings = listOf("kotlin""program")      
  6.    println(numbers.filter(::isPositive))      
  7.    println(strings.filter(::isPositive))      
  8. }    
Output
 
[6, 12]
[kotlin]
 

Property Reference

 
We can also access object property using the same :: operator.
 
The expression :: allows to retrieve its property name by using the name and the value with the help of the get() function.
 
To reset the value of property, reference property's set() method can be used.
 
Example
  1. fun main(args: Array<String>) {      
  2.    println(::x.get())      
  3.    println(::x.name)      
  4.    println(::y.set(20))      
  5. }      
  6. val x = 5      
  7. var y = 10    
Output
 
5
x
20 

Conclusion

 
Kotlin is quickly becoming a complete modern programming language. In this article, we learned about annotations and reflection in Kotlin. In the next part of this series, we will learn about Ranges. Stay Tuned!