skip to content

How do you rename a Kotlin property's getter or setter for Java callers using @JvmName, and what subtleties come with property accessors?

level: seniorimportance: should knowfreq 35%

answer

  1. Property -> getX()/setX() on JVM
  2. @get:JvmName / @set:JvmName use-site targets
  3. Or @JvmName on an explicit get()/set() block
  4. Renaming breaks JavaBean introspection
  5. Kotlin access unchanged; bytecode names change

basics

~10 s

Properties compile to getX()/setX() methods. You can use @get:JvmName and @set:JvmName to rename those generated methods for Java, while Kotlin still accesses the property normally.

solid answer

~40 s

A Kotlin property generates JVM accessor methods: `val x` -> `getX()`, `var x` -> `getX()`/`setX()` (and `is`-prefixed booleans keep the `is` name). To rename what Java sees, apply `@JvmName` with a **use-site target** on the accessor: `@get:JvmName("...")` and `@set:JvmName("...")`. You can place these on the property declaration. Kotlin callers still read/write the property by its name; only the bytecode accessor names change. Subtleties: (1) renaming a getter so it no longer follows the `getX` convention means Java won't treat it as a JavaBean property; (2) for a `var`, you typically rename both accessors consistently; (3) explicit accessor blocks can also carry `@JvmName`; (4) for top-level/extension properties and erasure-style clashes among properties, the accessor-targeted `@JvmName` is the same fix as for functions.

code

kotlin · 8 lines
kotlin
class Config {
    @get:JvmName("resolveTimeout")
    @set:JvmName("applyTimeout")
    var timeoutMs: Long = 5000
}

// Java:   config.applyTimeout(10000); long t = config.resolveTimeout();
// Kotlin: config.timeoutMs = 10000; val t = config.timeoutMs

go deeper

for a junior

Knows properties become getX()/setX() and that getters can be renamed for Java.

for a middle

Correctly uses @get:JvmName/@set:JvmName with use-site targets and knows Kotlin access is unaffected.

for a senior

Anticipates JavaBean-introspection breakage, handles var getter/setter consistency, and annotates explicit accessor blocks.

for a principal

Sets a team policy on accessor renaming, balancing Java ergonomics against framework/serialization compatibility and binary stability.

## Properties become accessor methods on the JVM Kotlin properties are not fields to Java by default — they compile to **getter/setter methods**: - `val name: String` -> `String getName()` - `var count: Int` -> `int getCount()` and `void setCount(int)` - A boolean-ish property named `isActive` keeps `isActive()` (no double `is`). ## Renaming accessors with use-site targets To change the **Java-visible accessor name**, annotate the property with a use-site-targeted `@JvmName`: ```kotlin class User(name: String) { @get:JvmName("fetchName") val name: String = name @get:JvmName("computedAge") @set:JvmName("updateAge") var age: Int = 0 } ``` - `@get:JvmName` renames the getter. - `@set:JvmName` renames the setter (only valid on a `var`). From Java: `user.fetchName()`, `user.computedAge()`, `user.updateAge(30)`. From Kotlin: still `user.name`, `user.age`, `user.age = 30`. ## You can also annotate explicit accessors ```kotlin val slug: String @JvmName("slugValue") get() = computeSlug() ``` Here `@JvmName` sits directly on the `get()` accessor; no use-site target is needed because it is already on the accessor. ## Subtleties and gotchas - **Breaks JavaBean convention:** if you rename a getter away from the `getX`/`isX` pattern, frameworks that rely on bean introspection (some serializers, older reflection-based libraries) will no longer recognize it as a property. Use this deliberately. - **var consistency:** for a `var`, decide whether you rename only the getter, only the setter, or both — mismatched names can confuse Java consumers. - **Boolean `is`-prefix:** Kotlin already maps `isX` properly; don't fight it unless you have a reason. - **Erasure clashes among properties:** two extension properties whose erased accessor signatures collide can be separated with `@get:JvmName`, exactly like the function case. - **No effect on Kotlin:** all renames are bytecode-only. ## Summary Properties expose getter/setter methods to Java; `@get:JvmName` / `@set:JvmName` (or `@JvmName` on an explicit accessor block) rename them, with the caveat that you may break bean-style introspection.

  • What can break if you rename a getter away from the getX convention?
    Bean-introspection-based tools (some serializers, reflective frameworks) won't recognize it as a property anymore, since they look for getX/isX accessors.
  • How do you rename a setter, and when is it invalid?
    Use @set:JvmName. It's only valid on a var (a val has no setter).

saying these in an interview costs you the question

  • Putting plain @JvmName on the property and expecting it to rename the getter without a use-site target
  • Using @set:JvmName on a val
  • Ignoring the JavaBean-introspection breakage
  • Claiming Kotlin property access also changes
  • Thinking properties are exposed to Java as raw fields by default

context