Kotlin: Calling Extension Functions from Java

Kotlin’s extension functions are a convenient way of attaching behavior to the most natural place it belongs. Extensions are incredibly handy to extend the behavior of classes you don’t control, or to define behavior that may only be useful to a subset of users of the class.

Here’s an example extension (I’d use this mainly in tests, not in production code) to convert an IANA timezone name (like “America/Los_Angeles”) into a Java ZoneId

/**
 * The IANA [ZoneId] for this string.
 *
 * For instance:
 *
 *     "America/Los_Angeles".zone == ZoneId.of("America/Los_Angeles")
 *
 */
val String.zone: ZoneId get() = ZoneId.of(this)

In Kotlin, using this extension is easy. The question is, if we’re working in a mixed Java+Kotlin codebase, how do we use a Kotlin extension in Java code?

These are the key concepts to using a Kotlin extension function/val from Java:

  • An extension is effectively equivalent to a Java static method, with the extension receiver passed as the first parameter.

  • Top-level Kotlin functions and vals can be treated as Java static methods if the file is annotated with @file:JvmName

  • A Kotlin val named x is usable from Java as getX

Thus if we annotate the file as:

@file:JvmName("ZoneExtensions")

package org.foobar

...

/**
 * The IANA [ZoneId] for this string.
 *
 * For instance:
 *
 *     "America/Los_Angeles".zone == ZoneId.of("America/Los_Angeles")
 *
 */
val String.zone: ZoneId get() = ZoneId.of(this)

We can then use the extension from Java as:

package org.foobar;

import static org.foobar.ZoneExtensions.getZone;

...

        getZone("Pacific/Honolulu")

Granted, with this particular example extension, we’d rather use ZoneId.of(...) from Java, but this is a useful option to have when your Kotlin extension function is non-trivial.