JvmStatic, JvmOverloads and JvmFields Annotations in Kotlin

Do not miss this exclusive book on Binary Tree Problems. Get it now for free.

Key Takeaways (JvmOverloads, JvmField, and JvmStatic)

  • `@JvmOverloads`, `@JvmField`, and `@JvmStatic` are annotations in kotlin to improve interoperability with the Java code.
  • `@JvmStatic` is used to mark a companion object function or property as a static method in the generated Java bytecode.
  • `@JvmOverloads` is used to generate overloads for the kotlin functions with default values in Java.
  • `@JvmField` is used to mark a kotlin attribute as public fields in Java code.

In this article, we will learn about three essential annotations in Kotlin programming for improving interoperability with Java code: @JvmOverloads, @JvmField, and @JvmStatic.

Table of Content

  1. JvmStatic
  2. JvmOverloads
  3. JvmField

In Kotlin Programming language, @JvmOverloads, @JvmField, and @JvmStatic are annotations used for improving the interoperability with the Java code.

As Kotlin is designed with Java interoperability in mind so that Kotlin code can be used seamlessly in Java projects and vice-versa so The annotations @JvmOverloads, @JvmField, and @JvmStatic in Kotlin are specifically used for improving interoperability with Java code.

Let's learn all three one by one.

JvmStatic

It is used to mark a companion object method/property as a static membets/methods in the generated Java bytecode. Now lets understand it using an example.

Without Annotation

class Engine {
    companion object {
        fun start() {}
    }
}

Calling start method:

In Kotlin

Engine.start()

As we can see in above code, We can access and call the start method of class Engine directly using the class name which is the desired behaviour of the companion object.

In Java

Engine.Companion.start()

But for Java code it is little different it is not working as a static field because we are accessing the start method using a Companion object. Now you may have doubt what is this Companion object? and why can't directly access it using class name as static members and methods should?

So simple answer is that Kotlin by default does not generate static members and methods but rather it store them in a object, This object is the Companion we're using in above example.

So, In order to generate static members and methods we annotate them using JvmStatic. Now lets see an example after annotating the method start with the JvmStatic.

With Annotation

class Engine {
    companion object {
        @JvmStatic fun start() {}
    }
}

Calling start method:

In Kotlin

Engine.start()

As we can see in above code, there is no difference for accessing and calling the start method in Kotlin is same.

In Java

Engine.start()

As we can see after the annotation we can directly access the start method in the Java too, Because this time instead of wrapping all the objects and members inside companion object in a Companion object it created define the method start as static.

JvmOverloads

In Kotlin, we can define a function or a constructor can have default parameters, but in Java, we have to define multiple versions of the function to simulate the same behavior. @JvmOverloads annotation is used to generate these overloaded versions for Java. lets understand using an example.

Without Annotation

class Point(
    x: Int = 0, 
    y: Int = 0, 
    z: Int = 0
)

Defining the class Point

In Kotlin

val p1 = Point()
val p2 = Point(x = 4)
val p3 = Point(x = 3)
val p4 = Point(x = 10, y = 11)
val p5 = Point(x = 10, y = 11, z = 2)

As we can see in the above code we can initialize class Point in different ways as all constructor parameters have default values, Which is the the desired behaviour we want.

In Java

Point p = new Point(0, 0, 0)

As we can see in the although we have default parameters in the class constructor then also we've to pass all arguments, To overload default parameters we use JvmOverloads

With Annotation

class Point @JvmOverloads(
    x: Int = 0, 
    y: Int = 0, 
    z: Int = 0
)

Defining the class Point

In Kotlin

val p1 = Point()
val p2 = Point(x = 4)
val p3 = Point(x = 3)
val p4 = Point(x = 10, y = 11)
val p5 = Point(x = 10, y = 11, z = 2)

As we can see in the above code Kotlin will have no change in initializing the class.

In Java

Point p = new Point()
Point p1 = new Point(10) // (x = 10)
Point p2 = new Point(10, 20) // (x = 10, y = 20)
Point p3 = new Point(10, 20, 30) // (x = 10, y = 20, z = 30)

No we can see in the code above that Kotlin generated overloads for the class constructor but someone of you may have doubt that why it created only 3 overloads? when there should be more than that like for x, y, z, (x, y), and so on...
The reason for that is to avoid ambiguity if there will be overloads for all then it will cause ambiguity like if we pass a single argument to the constructor it will not know which value is passed, is it x or y or z.

The overloads are generated from left to right because in Kotlin the default parameters are defined after the normal parameters.

JvmField

In Kotlin, properties are compiled with getters and setters it means if you want to operate on a property in Java you have to use getter/setter method for that property. @JvmField allows you to expose a property as a public field in Java. lets learn with an example.

class Config {
    var size = 100
}

Without Annotation

accessing Config attributes

In Kotlin

Config.size

In Java

Config.getSize()

As we can see in above codes for both Kotlin and Java that we can access attribute size normally but in Java we have to use getter for the property, The reason for this that by default all properties in Kotlin have backing field i.e. if no custom getter or setter are defined for an attribute Kotlin will generate default getters and setters. To use size as a public field in Java we have to annotate it using JvmField

With Annotation

class Config {
    `@JvmField` var size = 100
}

In Kotlin

Config.size

In Java

Config.size

Now we can see in above example we can access size as a public field.

With this article at OpenGenus.org, you must have the complete idea of JvmStatic, JvmOverloads and JvmFields Annotations in Kotlin.

Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.