Using @JvmOverloads and @JvmStatic for Kotlin interoperability with Java
Published: 2021-04-02 08:51:36

---
title: Using @JvmOverloads and @JvmStatic for Kotlin interoperability with Java
published: true
description: 
tags: 
//cover_image: 
---
Kotlin promises interoperability with Java. Today(31/03/2020), I found out that we sometimes need to do a little extra to make interoperability with Java seamless and natural using a couple of annotations. I never really had a use case for Java interoperability, mainly because I have been working in Kotlin-only projects since 2018.

I had the chance to rewrite a simple open source [library](https://github.com/emmanuelkehinde/Shutdown) in Kotlin. During the rewrite, I failed to consider that there could be Android apps written in Java that already depend on the library till the owner of the library drew my attention to that fact. In order to not break existing applications that already depend on this library, I had to find a solution. And that's what led me to `@JvmOverloads` and `@JvmStatic` annotations. 

The Java implementation of the library exposes a single static method with three(3) overloads. Rewriting this in Kotlin was quite simple. 

```java
// Shutdown.java
public static void now(Activity context){
        if (context != null){
            init(context, DEFAULT_MESSAGE, DEFAULT_TIMEOUT);
        }
    }

    public static void now(Activity context, String message){
        if (context != null && !message.isEmpty()){
            init(context, message, DEFAULT_TIMEOUT);
        }
    }

    public static void now(Activity context, long timeout){
        if (context != null && timeout != 0){
            init(context, DEFAULT_MESSAGE, timeout);
        }
    }

    public static void now(Activity context, String message, long timeout){
        if (context != null && !message.isEmpty() && timeout != 0){
            init(context, message, timeout);
        }
    }
```

```kotlin
// Shutdown.kt

...// inside companion object

fun now(context: Activity?, message: String = DEFAULT_MESSAGE, timeout: Long = DEFAULT_TIME_OUT) {
	context?.let { init(context, message, timeout) }
}
```

Calling the Kotlin implementation of `now(context)` from a Kotlin class works without issues. Calling this Kotlin implementation from a Java class will show you the red squiggly line. 

```java
// SomeActivityClass.java

Shutdown.now(this); // no issues
```

```java
//SomeActivityClass.kt

Shutdown.Companion.now(this); // Compile time error. Breaking change?? 😱
```

The compile-time error message read that three(3) arguments were expected but only one(1) was found. Which was strange because I provided default values to the other two arguments in Kotlin. Upon further investigation, I found that the Kotlin compiler wasn't generating the overloads for `now(context)` so it was impossible to omit some arguments when calling from Java. In comes the `@JvmOverloads` annotation. This annotation essentially instructs the Kotlin compiler to generate overloads for `now(context)`. 

```kotlin
// Shutdown.kt

@JvmOverloads
fun now(context: Activity?, message: String = DEFAULT_MESSAGE, timeout: Long = DEFAULT_TIMEOUT)
    context?.let { init(it, message, timeout) }        
}
```

Adding `@JvmOverloads` resolves the compile-time error. And now we can call `now(context)` from Java with one(1) or more arguments. But the Java usage still didn't feel natural. It didn't feel like a static method call. And that's what led me to `@JvmStatic`. This annotation tells the Kotlin compiler to generate an extra static method for `now(context)`. 

```kotlin
// Shutdown.kt

@JvmOverloads
@JvmStatic
fun now(context: Activity?, message: String = DEFAULT_MESSAGE, timeout: Long = DEFAULT_TIMEOUT)
    context?.let { init(it, message, timeout) }        
}
```

```java
// SomeActivity.java

Shutdown.now(this);
```

Now the Java client doesn't need to access `Companion` in order to use `now(context)` from Java. Order has finally been restored in our Java client after the Kotlin rewrite. No more breaking changes! You can find the Pull Request [here](https://github.com/emmanuelkehinde/Shutdown/pull/4), if interested. 

Thanks to [Eyram A. Agbe](https://www.linkedin.com/in/eyram-agbe-748a13160/), Raymond(creator of [Playlistor](http://playlistor.io)), [Waheed Derby](https://wadederby.com) and [Wilfred](https://twitter.com/will_power) for taking the time to review this article.