skip to content

Java Interop

How Kotlin and Java call each other: platform types at the nullability boundary, SAM conversions, the @Jvm annotations that shape emitted members, type mapping, and the traps in between. Every real Kotlin codebase is a mixed codebase, so this comes up constantly.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

116 · 5 sections

Why can Kotlin and Java call each other so seamlessly? Explain the underlying model that makes interop possible.

level: juniorimportance: must knowfreq 70%
basics
~20 s

Both Kotlin and Java compile into the same kind of code the JVM runs (bytecode). A Kotlin class becomes a normal JVM class, so Java sees it as just another class, and vice versa. No bridge or wrapper is needed.

open as a page

What is a platform type in Kotlin, why does it exist, and what risk does it introduce?

level: middleimportance: must knowfreq 68%
basics
~20 s

When Kotlin calls Java, Java values have no nullability info, so Kotlin can't tell if they can be null. It treats them as 'platform types' and trusts you. If you assume non-null but it's actually null, you get an NPE.

open as a page

What do @JvmStatic, @JvmField, @JvmName, @JvmOverloads, and @JvmMultifileClass do, and when would you reach for each?

level: middleimportance: should knowfreq 60%
basics
~20 s

These @Jvm* annotations change the Java-facing shape of compiled Kotlin so Java can call it naturally — making members static, exposing plain fields, renaming, generating overloads for default arguments, or merging top-level functions into one class.

open as a page

Explain how Kotlin maps types to the JVM: mapped types, primitives vs boxing, and what happens to Kotlin-only types like Unit and Nothing.

level: seniorimportance: should knowfreq 50%
basics
~20 s

Many Kotlin types are just renamed JVM types (Kotlin String is Java String). Numbers use fast primitives when possible and box only when they must be nullable or generic. Unit becomes void-like; some types like Nothing have no real runtime value.

open as a page

When mixing Kotlin and Java, how do SAM conversions, Kotlin properties, and the read-only/mutable collection split behave across the boundary?

level: seniorimportance: nice to knowfreq 38%
basics
~20 s

A Kotlin lambda can stand in for a Java single-method interface (SAM conversion). Kotlin properties show up as getX/setX to Java. And Kotlin's read-only vs mutable list distinction disappears at runtime, so Java can still mutate a 'read-only' list.

open as a page

When you call a Java method that takes an int[] from Kotlin, what Kotlin type do you pass, and why not Array<Int>?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Use Kotlin's IntArray for a Java int[]. Array<Int> is an array of boxed Integer objects (Integer[]), which is a different Java type and won't match an int[] parameter.

open as a page

In Kotlin, what is the difference between List and MutableList, and where does that distinction actually exist at runtime?

level: juniorimportance: must knowfreq 70%
basics
~20 s

List has no add or remove methods, MutableList does. But it's only a rule the compiler checks. At runtime both are usually the same Java ArrayList, so the read-only promise can be broken from Java code.

open as a page

When you call a Java class from Kotlin, how do you read a value exposed by a Java getter like getName()? Show both ways Kotlin lets you access it.

level: juniorimportance: must knowfreq 80%
basics
~10 s

Kotlin lets you write obj.name instead of obj.getName(). It turns Java get/set methods into a property you read and write with a dot. You can still call obj.getName() the old way too.

open as a page

How do you call a Java static method and read a Java static field (like Integer.parseInt or Integer.MAX_VALUE) from Kotlin?

level: juniorimportance: must knowfreq 75%
basics
~10 s

You call them directly on the class name, just like in Java: Integer.parseInt("42") and Integer.MAX_VALUE. There is no special import or wrapper needed.

open as a page

What is a Kotlin platform type, why does it show up as String! in the IDE, and what happens to null checking when you use one?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A platform type is a value coming from Java whose nullability Kotlin can't know. The compiler relaxes null checks for it. If you treat it as non-null but it's actually null, you get a NullPointerException at runtime.

open as a page

You have a Kotlin class with a companion object containing a function create(). How do you call that function from Java, and why isn't the call simply Foo.create()?

level: juniorimportance: must knowfreq 70%
basics
~10 s

From Java you call Foo.Companion.create(). Kotlin puts companion members on a nested object named Companion, so Java must go through that object rather than calling the method straight on the class.

open as a page

A Kotlin file Utils.kt declares a top-level function fun greet(): String. How does Java call it, and where does that method actually live on the JVM?

level: juniorimportance: must knowfreq 65%
basics
~10 s

Kotlin puts top-level functions into an auto-generated class named after the file plus 'Kt'. So Utils.kt's greet() is called from Java as UtilsKt.greet().

open as a page

What does the @JvmField annotation do, and why would you use it when calling Kotlin code from Java?

level: juniorimportance: must knowfreq 55%
basics
~10 s

@JvmField turns a Kotlin property into a plain public field. Java code can then read or write it directly as obj.x instead of calling getX() or setX().

open as a page

What does the @JvmName annotation do, and why would you put it on a Kotlin function or property accessor that Java code will call?

level: juniorimportance: must knowfreq 55%
basics
~20 s

@JvmName changes the name that a Kotlin function, getter, or setter shows up as when called from Java. It lets you give Java a nicer name or avoid a name conflict, without changing the Kotlin name.

open as a page

What does the @JvmOverloads annotation do, and why is it needed for Java callers?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Java cannot use Kotlin's default argument values. @JvmOverloads tells the compiler to also generate extra Java-visible overloads, one per default-parameter combination, so Java code can call the function while leaving some arguments out.

open as a page

You write a Kotlin function fun greet(name: String, greeting: String = "Hello"). A Java colleague says they can only call it by passing both arguments. Why can't Java omit the defaulted parameter, and what is the simplest fix?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Kotlin default values live only in Kotlin metadata, not in the compiled method signature Java sees. So Java must pass every argument. Adding @JvmOverloads makes Kotlin also generate the shorter overloads Java can call.

open as a page

When a Kotlin interface has a method with a body (a default implementation), how is that body compiled for the JVM by default, and what is the DefaultImpls class?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Kotlin lets interface methods have a body. By default the compiler does not put that body on the JVM interface itself; it copies it into a hidden helper class so classes implementing the interface can reuse it.

open as a page

When you declare `var count: Int` in a Kotlin class, what does Java code see when it uses that class?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Java does not see a public field. It sees a private hidden field plus two methods: getCount() to read it and setCount() to change it. Java must call those methods.

open as a page

When you write a Kotlin function that takes a kotlin.Int parameter, what Java type does it become in the compiled bytecode, and when would it instead become java.lang.Integer?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Kotlin's Int usually compiles to Java's primitive int, which is fast and uses no extra memory. But when the value can be null or is used as a generic type argument, Kotlin boxes it into Integer instead.

open as a page

How does a Kotlin function that returns Unit appear when called from Java, and what is the JVM bytecode return type?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A Kotlin function returning Unit looks like a normal void method in Java. The JVM return type is void, so Java callers just call it and get nothing back.

open as a page

What is a 'platform declaration clash' in Kotlin, and what commonly causes it?

level: juniorimportance: must knowfreq 55%
basics
~10 s

It is a compile error that happens when two Kotlin functions look different in Kotlin but turn into the exact same method on the JVM, so the JVM cannot tell them apart.

open as a page

What is a Kotlin 'platform type' and why can a value coming from Java code throw a NullPointerException even though your Kotlin code looks fully null-safe?

level: juniorimportance: must knowfreq 75%
basics
~20 s

When Java returns a value, Kotlin doesn't know if it can be null, so it trusts you. If you treat it as non-null and it actually is null, you only crash later when you use it.

open as a page

When a Java developer calls into a Kotlin class that has a companion object, what is the 'Companion' field they see in autocomplete, and how should they reach the companion's members from Java?

level: juniorimportance: must knowfreq 58%
basics
~10 s

Kotlin turns a companion object into a static field named Companion plus a nested class. From Java you call MyClass.Companion.method(), unless the member is annotated @JvmStatic, which lets you call MyClass.method() directly.

open as a page

In Kotlin, what is a use-site annotation target, and why might you write `@field:NotNull` instead of just `@NotNull` on a property?

level: juniorimportance: must knowfreq 55%
basics
~10 s

A single Kotlin property turns into several Java elements (field, getter, setter, constructor parameter). A use-site target like @field: tells the compiler which of those elements the annotation should land on.

open as a page

Show how to resolve a generic-erasure platform clash for two overloads using @JvmName, and explain what each annotation changes.

level: middleimportance: must knowfreq 50%
basics
~10 s

Put @JvmName with a different name on at least one of the clashing functions. That gives each a unique method name in the compiled code, so the JVM no longer sees a duplicate.

open as a page