skip to content

@JvmOverloads

Java cannot use Kotlin's default arguments, so @JvmOverloads generates the overload ladder for you. Interviewers ask because forgetting it is the classic reason a Kotlin API feels hostile from Java.

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

questions

5

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

level: juniorimportance: must knowfreq 70%

answer

  1. Java can't see Kotlin defaults
  2. Generates real JVM overloads
  3. Drops defaults right-to-left
  4. N+1 overloads
  5. Interop convenience, no change for Kotlin

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.

solid answer

~40 s

Kotlin default parameter values live in the Kotlin function and Java callers can't supply them, so from Java you'd always have to pass every argument. Adding @JvmOverloads to a function or constructor makes the compiler emit additional JVM-visible overloaded methods/constructors: one for the full signature plus one for each trailing-defaults combination, dropping defaulted parameters from the right. So fun greet(name: String, greeting: String = "Hi", loud: Boolean = false) produces three Java-callable overloads: greet(name), greet(name, greeting), greet(name, greeting, loud). It changes nothing for Kotlin callers — they already use defaults directly. It's purely an interop convenience for Java (and other JVM languages) consuming the Kotlin API.

code

kotlin · 5 lines
kotlin
@JvmOverloads
fun connect(host: String, port: Int = 8080, secure: Boolean = false) {
    // ...
}
// Java gets: connect(host), connect(host, port), connect(host, port, secure)

go deeper

for a junior

Knows Java can't use Kotlin defaults and that @JvmOverloads creates extra Java-callable overloads.

for a middle

Can predict exactly which overloads are generated and that defaults drop right-to-left.

for a senior

Explains it's compiler-generated forwarding methods, applies to constructors, and is a no-op for Kotlin callers.

for a principal

Frames it as an API-surface/interop design decision and weighs it against alternatives like builders or explicit overloads.

## The problem In Kotlin you can give parameters **default values**: ```kotlin fun greet(name: String, greeting: String = "Hi", loud: Boolean = false): String { val msg = "$greeting, $name" return if (loud) msg.uppercase() else msg } ``` Kotlin callers can omit defaulted arguments: `greet("Ada")`. But this default mechanism is a **Kotlin compiler feature**, not a JVM feature. The JVM has no notion of default arguments. Under the hood Kotlin compiles ONE method `greet(String, String, boolean)` plus a hidden synthetic helper that fills in defaults — but Java cannot call that helper conveniently. So from **Java**, by default you must pass every argument: ```java Kt.greet("Ada", "Hi", false); // must supply all three ``` ## What @JvmOverloads does Annotating the function (or constructor) tells the Kotlin compiler to **generate extra real overloads** visible to the JVM — one per combination of trailing defaults, removing defaulted parameters **from right to left**: ```kotlin @JvmOverloads fun greet(name: String, greeting: String = "Hi", loud: Boolean = false): String { /* ... */ } ``` Now Java sees three methods: ```java Kt.greet("Ada"); // greeting="Hi", loud=false Kt.greet("Ada", "Hello"); // loud=false Kt.greet("Ada", "Hello", true); ``` Each generated overload simply forwards to the full method using the default values. ## Key facts - It generates **N+1** overloads where N is the number of parameters with defaults (the full one plus one per removed trailing default). - Defaults are dropped **right-to-left only** — there is no overload that keeps `loud` but drops `greeting`. - It works on **top-level functions, member functions, and constructors**. - For **Kotlin callers nothing changes**: they keep using the single function with named/default arguments. - It is purely a JVM **interop** affordance — useful for Java, Android framework code (e.g. custom `View` constructors), Spring, mocking frameworks, etc. ## Without vs with Without the annotation, Java gets only the maximal-arity method. With it, Java gets a friendly ladder of overloads matching what Kotlin callers enjoy via defaults.

  • Does @JvmOverloads change anything for Kotlin callers?
    No. Kotlin callers still use the single function with default and named arguments; the extra overloads are only emitted for JVM/Java visibility.
  • How many methods are generated if there are 2 defaulted parameters?
    Three: the full-arity method plus one dropping the last default and one dropping both — i.e. N+1 where N=2.

It's like a restaurant translating a 'build-your-own combo' into a printed menu of fixed combos, because Java customers can't order off the custom builder.

saying these in an interview costs you the question

  • Claiming Java can call Kotlin default arguments directly without it
  • Saying it changes behavior or signatures for Kotlin callers
  • Thinking it generates overloads for every subset of parameters, not just trailing ones
  • Confusing it with @JvmStatic or @JvmName

context

open as a page

Given fun box(w: Int, h: Int = 1, color: String = "red", filled: Boolean = true) annotated with @JvmOverloads, which exact method signatures become visible to Java?

level: middleimportance: must knowfreq 55%

basics

~10 s

Java sees one method per trailing-defaults combination: box(w), box(w,h), box(w,h,color), and box(w,h,color,filled). Three parameters have defaults, so four overloads total, each dropping defaults from the right.

open as a page

How do you apply @JvmOverloads to a primary constructor, and why is this a common pattern for Android custom Views?

level: middleimportance: should knowfreq 45%

basics

~10 s

Put @JvmOverloads on the primary constructor, after the visibility/constructor keyword: class MyView @JvmOverloads constructor(...). It generates the multiple constructors Android's layout-inflation and Java code expect, so you don't hand-write three or four constructors.

open as a page

What are the limitations and common pitfalls of @JvmOverloads — when does it not apply or cause clashes?

level: seniorimportance: should knowfreq 35%

basics

~20 s

It only helps with trailing defaults dropped right-to-left, needs at least one defaulted parameter to do anything, doesn't work on abstract/interface methods, and can clash with hand-written overloads. It also enlarges your public API surface.

open as a page

When designing a Kotlin library API consumed by Java, how do you decide between @JvmOverloads, explicit overloads, and a builder — and what binary-compatibility tradeoffs matter?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Use @JvmOverloads for simple trailing-optional parameters where Java just wants to omit the last few. Use explicit overloads when you need non-trailing combinations or different bodies. Use a builder when there are many independent optional fields. Remember each generated overload becomes part of your binary API.

open as a page