100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Kotlin

Kotlin-Java Interoperability

Explore how Kotlin and Java code can call each other seamlessly on the JVM, and the nuances that come with it.

Coroutines & Error HandlingIntermediate8 min readJul 8, 2026
Analogies

Introduction

Kotlin compiles to JVM bytecode, which means Kotlin code can call Java code directly and Java code can call Kotlin code directly. This seamless interoperability is one of the biggest reasons Kotlin gained rapid adoption: teams could introduce it incrementally into existing Java or Android codebases without rewriting everything at once.

🏏

Cricket analogy: Like an overseas player joining a domestic T20 franchise mid-season and slotting straight into the batting order without the whole squad needing to relearn the game, Kotlin code calls Java code directly on the same JVM.

Syntax

kotlin
// Kotlin calling a Java class
val list = java.util.ArrayList<String>()
list.add("Kotlin")

// Exposing Kotlin members as true Java statics
class Config {
    companion object {
        @JvmStatic
        fun defaultName() = "SkillVeris"

        @JvmField
        val VERSION = "1.0"
    }
}

Explanation

Because Kotlin and Java both target the JVM, Kotlin classes and functions are visible to Java code, sometimes with naming adjustments handled by annotations. Companion object members are not true static members by default; the @JvmStatic annotation exposes a companion function as a real static method callable from Java, while @JvmField exposes a property as a plain static field instead of a getter/setter pair. When Kotlin consumes Java APIs, types whose nullability is unknown appear as platform types, notated internally as something like String!. The Kotlin compiler does not enforce null-safety checks on platform types, so the developer is responsible for handling potential nulls correctly.

🏏

Cricket analogy: Like a team's vice-captain (companion object) who can call plays from the pavilion without being on the official playing XI (a true static member), @JvmStatic promotes that vice-captain to an on-field captain Java can address directly.

Example

kotlin
// Java class (User.java)
// public class User {
//     public String getName() { return null; }
// }

fun greet(user: User) {
    val name = user.name // platform type String!, no compile-time null check
    println("Hello, ${name.uppercase()}") // may throw NullPointerException at runtime
}

// Output:
// Exception in thread "main" java.lang.NullPointerException

Key Takeaways

  • Kotlin compiles to JVM bytecode, enabling two-way calls between Kotlin and Java.
  • @JvmStatic exposes companion object functions as true Java static methods.
  • @JvmField exposes a Kotlin property as a plain Java static field.
  • Platform types like String! represent Java types with unverified nullability.
  • The compiler does not enforce null-safety on platform types, shifting responsibility to the developer.
  • This interop enabled incremental Kotlin adoption in existing Java and Android codebases.

Practice what you learned

Was this page helpful?

Topics covered

#Kotlin#KotlinProgrammingStudyNotes#Programming#KotlinJavaInteroperability#Java#Interoperability#Syntax#Explanation#StudyNotes#SkillVeris