skip to content

Why can't you use named arguments when calling Java methods from Kotlin, and how does this interact with varargs?

level: seniorimportance: should knowfreq 45%

answer

  1. Java bytecode drops parameter names by default
  2. named args forbidden when callee is Java
  3. -parameters doesn't enable Kotlin named calls
  4. spread * to pass array into a vararg
  5. can't name a Java vararg argument

basics

~10 s

Java bytecode usually doesn't keep parameter names, so Kotlin can't reliably match a name to a Java method's parameter. Therefore Kotlin forbids named arguments on calls to Java methods; you must pass them positionally.

solid answer

~40 s

Named arguments rely on parameter names being part of the API. Java .class files don't retain parameter names unless compiled with -parameters, and even then Kotlin does not honor them for named-argument calls — so Kotlin disallows the name = value syntax when the callee is a Java method. You call Java methods positionally. This also affects varargs: when passing values to a Java vararg from Kotlin you use the spread operator (*) on an array, and you cannot name a Java vararg argument. The rule is a deliberate safety measure: relying on names that may be absent or compiler-dependent would make calls fragile. For Kotlin-declared functions, names are always available from metadata, so named arguments work fully.

code

kotlin · 5 lines
kotlin
// Java: void configure(int width, int height, String... tags)

val tags = arrayOf("a", "b")
configure(800, 600, *tags)          // positional + spread: OK
// configure(width = 800, height = 600, *tags)  // ERROR: named args not allowed for Java methods

go deeper

for a junior

Knows Java methods are called positionally and that named args don't work there.

for a middle

Explains it's because Java bytecode lacks parameter names by default, and uses spread for varargs.

for a senior

Adds that -parameters still doesn't enable named calls, and explains the named-vararg-needs-single-spread nuance.

for a principal

Articulates the API-stability rationale for keeping names a Kotlin-only contract and the cross-language design tradeoff.

## Where parameter names live Named arguments bind a value to a parameter **by name**, so the name must be a dependable part of the callee's API. - For **Kotlin** functions, parameter names are stored in Kotlin metadata and are always available to the compiler — named arguments work everywhere. - For **Java** methods, parameter names are **not retained in bytecode by default**. They appear only if the class was compiled with the `javac -parameters` flag, and historically tooling couldn't rely on this. Because the name may be missing or unreliable, Kotlin makes a clean rule: **you cannot use named-argument syntax when calling a Java method.** You must pass arguments positionally. ```kotlin // Java: void setColor(int red, int green, int blue) // Kotlin call: obj.setColor(255, 0, 0) // OK, positional // obj.setColor(red = 255, ...) // ERROR: named args not allowed for Java methods ``` ## Interaction with varargs Java varargs add a related limitation: - To pass an existing array to a Java (or Kotlin) **vararg** parameter, Kotlin uses the **spread operator** `*`: ```kotlin val names = arrayOf("a", "b") javaObject.printAll(*names) // spread into a Java String... param ``` - You **cannot name** a Java vararg argument, consistent with the no-named-args-for-Java rule. - Even for **Kotlin** functions, a vararg parameter passed by name must receive a **single spread array** (`vararg = *arr`), not a comma-separated list — naming and the multi-value vararg syntax don't combine. ## Why this is the right tradeoff Allowing named arguments against possibly-absent Java parameter names would make code compile or break depending on how a dependency was built. Kotlin prefers a predictable boundary: names are a first-class part of **Kotlin** signatures only. ## Quick checklist - Calling a Java method? Positional only; no `name = value`. - Passing an array to any vararg? Use `*array`. - Naming a Kotlin vararg? Pass exactly one spread array.

  • Does compiling the Java code with -parameters enable Kotlin named-argument calls?
    No. Even when names are present in bytecode, Kotlin still disallows named arguments for Java methods, keeping the boundary predictable.
  • How do you pass an existing array into a vararg parameter?
    Use the spread operator: f(*array). Without it you'd be passing the array itself as a single element.

saying these in an interview costs you the question

  • Saying named arguments work for Java methods if you import them right
  • Believing -parameters re-enables named calls in Kotlin
  • Confusing spread (*array) with simply passing the array
  • Claiming you can name a Kotlin vararg with a comma-separated list of values

context