Explain Codes LogoExplain Codes Logo

Accessing Kotlin extension functions from Java

java
interoperability
kotlin-java-interoperability
java-interop
Anton ShumikhinbyAnton Shumikhin·Nov 2, 2024
TLDR

To access Kotlin extension functions in Java, treat them as static methods. These are packaged in a class, named after the Kotlin file they belong to, with Kt suffix. Given an extension function in StringExtensions.kt:

// In Kotlin fun String.greet(): String = "Hello, $this!"

You'd access it in Java in this manner:

// In Java String result = StringExtensionsKt.greet("World"); // We're using a 'Kt' on the tail, not a tail on a cat.

Defining a custom naming convention for the calling class in Java

You can utilize Kotlin's @JvmName annotation to define a custom class name for Java.

// At the top of your Kotlin file @file:JvmName("DemoUtils") // Giving Java a name it can pronounce fun String.exclaim(): String = "$this!"

And in Java, you refer to DemoUtils instead of StringExtensionsKt.

// In Java String excited = DemoUtils.exclaim("Hello, World"); // Ah! A name I recognize.

Matching understandings between Kotlin and Java

In the generated Java class, the receiver type (the class being extended in Kotlin) appears as the first parameter of the associated static method.

// Kotlin fun String.multiply(times: Int): String = repeat(times) // 'this' in Kotlin-land is 'String' in Java-land.

This function in Java requires the String object as the first parameter:

// Java String repeated = StringExtensionsKt.multiply("hi", 3); // 'this' is now 'hi'. 'hi' is happy to be first.

Borrowing Kotlin's awesome sauce in Java classes

Use static imports to leverage convenience in your Java classes, mimicking Kotlin's dot-syntax.

// Java import static your.package.StringExtensionsKt.*; public class JavaUsage { // Borrow Kotlin's magic and use it here. public void printGreeting() { System.out.println(greet("Java User")); } }

Java's nullability annotations keep Kotlin's null safety

Annotate parameters in Java with @NotNull or @Nullable. Kotlin respects these annotations. It informs the Kotlin compiler of nullability. Check this Kotlin function:

// Kotlin fun String?.orEmpty(): String = this ?: "" // Defusing Kotlin's nullable bomb.

Java, remember that null is a possibility:

// Java String maybeNull = possiblyNullString.orEmpty(); // null or not null. That's the question.

Predictable patterns of generated classes

Kotlin creates classes for Java to use following an understandable convention. A MyExtensions.kt file results in:

// Java import static com.example.MyExtensionsKt.*; // Clever Kotlin. Changing MyExtensions.kt into MyExtensionsKt. See what it did there?

A convention you can trust unless @JvmName is playing.

Kotlin to Java tricks

Experience enhancement by knowing these interoperability tricks:

  • Use @JvmOverloads for functions with default params.
  • @JvmStatic helps you access methods from Java without an instance within companion objects.
  • @JvmField directly exposes fields with the same visibility in Java.