Open In App

Java Interoperability - Calling Kotlin from Java

Last Updated : 08 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

When Kotlin was first developed, it was designed to run on the Java Virtual Machine (JVM). As a result, Kotlin offers seamless interoperability with Java. This means we can easily call Kotlin code from Java, just like we do with Java classes and methods. However, there are some specific rules and behaviors to keep in mind when accessing Kotlin features from Java. In this article, we will understand the key points of using Kotlin code in Java.

Kotlin Properties

In Kotlin, a property such as

var age: Int

is compiled into Java as a private field along with corresponding getter and setter methods. For the above property, the generated Java code would look like as shown below.

private int age;
public int getAge() { ... }
public void setAge(int value) { ... }

We can access the property in Java using standard method calls as show below.

Person person = new Person();
int age = person.getAge();
person.setAge(25);

If a Kotlin property starts with the keyword is, for example:

var isActive: Boolean

then the getter in Java will be named isActive() instead of getIsActive().

Package-level Functions

In Kotlin, functions can be declared at the top level (outside any class). When compiled, these functions become static methods inside a generated Java class. The name of the generated class is based on the Kotlin file name.

Example: firstProgram.kt

Kotlin
package kotlinPrograms

fun add(a: Int, b: Int): Int = a + b

This function can be invoked in Java using the following syntax:

int result = kotlinPrograms.FirstProgramKt.add(3, 5);

Changing the Generated Class Name

We can change the name of the generated Java class using @JvmName annotation.

Kotlin
@file:JvmName("Sample")
package kotlinPrograms

fun add(a: Int, b: Int): Int = a + b

This function can be invoked in Java using the following syntax:

int result = kotlinPrograms.Sample.add(3, 5);

Handling Multiple Files with the Same Name

If we have multiple Kotlin files with the same name, it may lead to name conflicts. To combine them into a single Java class, we use the @JvmMultifileClass annotation in each file:

Example - First Kotlin File:

Kotlin
@file:JvmMultifileClass
@file:JvmName("Sample")
package sample.example

fun print() = println("Hello")

Example - Second Kotlin File:

Kotlin
@file:JvmMultifileClass
@file:JvmName("Sample")
package sample.example

fun printString() = println("World")

Both these functions can be invoked in Java using the following syntax:

sample.example.Sample.print();
sample.example.Sample.printString();

Static fields

In Kotlin, if we want a property to behave like a static field in Java, we declare it inside a companion object or object, and use the @JvmField annotation, or the const modifier.

Example:

Kotlin
class Program {
    companion object {
        @JvmField val x = 10
        const val y = 20
    }
}

This function can be invoked in Java using the following syntax:

int val1 = Program.x;
int val2 = ProgramKt.y;

Static methods

The methods defined at the package level are always generated as static methods in the Java file. Also the methods defined in named objects and companion objects if annotated with @JvmStatic annotation are generated as static methods. This annotation declares the following function to be a class function.

Example:

Kotlin
class Example {
    companion object {
        @JvmStatic fun add() = println("Add")
        fun sub() = println("Subtract")
    }
}

This function can be invoked in Java using the following syntax:

Example.add(); // Works: static method
Example.sub(); // Error: not static
Example.Companion.sub(); // Works: accessed via Companion object

This same behavior applies to Kotlin object declarations as well.

Instance Fields

Kotlin provides a feature to use a property as an instance field in Java. To do this annotate the property with @JvmField annotation. These instance fields have the same visibility as the Kotlin property. However, the property must have a backing field and must not be declared with private, open, const and override modifiers.

Example

Kotlin
class ABC(val value: Int) {
    @JvmField var id: Int = 0
}

This property now can be accessed in Java as

ABC obj = new ABC(5);
System.out.println(obj.id);

Checked Exceptions

All exceptions in Kotlin are unchecked. This means Kotlin functions do not declare checked exceptions in their signatures. If we want Java code to handle Kotlin exceptions properly, we need to use the @Throws annotation.

Example:

Kotlin
@Throws(IOException::class)
fun print() {
    throw IOException("IO error")
}

This function now can be accessed in Java as:

try {
Sample.Program.print();
} catch (IOException e) {
// Handle exception
}

Without the @Throws annotation, the Java compiler will not recognize that the function might throw a checked exception, and it will result in a compilation error.


Next Article
Article Tags :

Similar Reads