skip to content

A Kotlin property's generated getter clashes with a function. Explain the mechanism and how to resolve it.

level: middleimportance: should knowfreq 35%

answer

  1. Property -> JavaBean getX/setX/isX
  2. fun getX() collides with val x
  3. Boolean isReady -> isReady()/setReady()
  4. @get:/@set:JvmName renames accessor
  5. Renaming getter can break bean introspection

basics

~20 s

A Kotlin property quietly generates a getter method like getX(). If you also write a function named getX(), both produce the same JVM method, so they clash. Rename one with @JvmName, or rename the function.

solid answer

~30 s

Every Kotlin property compiles to a backing field plus accessor methods following JavaBean conventions: `val/var x` emits `getX()` (and `setX(...)` for `var`); a `Boolean` named `isReady` keeps `isReady()`. If you also declare a function whose JVM name equals that accessor — e.g. `fun getX(): T` alongside `val x: T` — both target `getX()` and the compiler reports a platform declaration clash. Resolve it by renaming the accessor with `@get:JvmName("...")`/`@set:JvmName("...")` use-site targets, by giving the function a `@JvmName`, or simply by renaming the Kotlin function. This is the non-generic flavor of signature clash: erasure isn't involved, just the auto-generated accessor naming convention.

code

kotlin · 7 lines
kotlin
class Toggle {
    // val enabled generates getEnabled()/isEnabled depending on type
    @get:JvmName("enabledFlag")
    val enabled: Boolean = true

    fun getEnabled(): Boolean = false  // would clash without the rename above
}

go deeper

for a junior

Knows properties become getX/setX and that a matching function can clash.

for a middle

Picks the right fix (@get:JvmName vs rename) and knows the is-prefix accessor rules.

for a senior

Anticipates framework introspection impact when renaming accessors and chooses the least disruptive fix.

for a principal

Sets naming conventions that keep Kotlin properties and Java bean discovery compatible across the API.

## How properties become methods Kotlin has no fields in its language model — it has **properties**. On the JVM each property is lowered to: - a private **backing field**, - a **getter** named per JavaBean rules: `val name` -> `getName()`; `var name` -> `getName()` + `setName(x)`; a `Boolean val isOpen` -> `isOpen()` (the `is` prefix is preserved, no extra `get`). ## The collision ```kotlin class Account { val balance: Int = 0 // generates getBalance() fun getBalance(): Int = 0 // also targets getBalance() -> CLASH } ``` The property and the function both want the JVM symbol `getBalance()`. Same descriptor -> *platform declaration clash*. No generics needed; it is purely the accessor naming convention. ## Fixes 1. Rename the **accessor** with a use-site target: ```kotlin class Account { @get:JvmName("balanceValue") val balance: Int = 0 fun getBalance(): Int = 42 } ``` 2. Rename the **function**'s JVM symbol: ```kotlin class Account { val balance: Int = 0 @JvmName("computeBalance") fun getBalance(): Int = 42 } ``` 3. Best: avoid `get`-prefixed function names entirely — they read like accessors anyway. Just name the function `currentBalance()`. ## `is`-prefix subtlety A `Boolean` property named `isReady` produces `isReady()`/`setReady(...)`. A function `fun isReady(): Boolean` clashes with the getter the same way. The setter is `setReady`, dropping the `is`. ## Why it matters for interop Java frameworks (Jackson, Spring, JPA) discover properties via `getX`/`isX`/`setX`. Renaming an accessor with `@get:JvmName` can silently break bean introspection, so resolve clashes thoughtfully rather than reflexively renaming the getter.

  • What JVM accessor does a `Boolean` property `var isActive` generate?
    Getter isActive() (the `is` prefix is kept) and setter setActive(...) (the `is` is dropped for the setter).
  • Why might @get:JvmName be risky in a Spring/JPA entity?
    Frameworks introspect bean accessors by getX/isX naming; renaming the getter can hide the property from data binding or persistence.

saying these in an interview costs you the question

  • Not knowing properties generate getX/setX/isX methods
  • Claiming erasure is involved (it is not here)
  • Renaming a getter in an entity without considering bean introspection
  • Confusing the is-prefix setter naming (setReady, not setIsReady)

context