A Kotlin property's generated getter clashes with a function. Explain the mechanism and how to resolve it.
answer
- Property -> JavaBean getX/setX/isX
- fun getX() collides with val x
- Boolean isReady -> isReady()/setReady()
- @get:/@set:JvmName renames accessor
- Renaming getter can break bean introspection
basics
~20 sA 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 sEvery 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 linesclass 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
Knows properties become getX/setX and that a matching function can clash.
Picks the right fix (@get:JvmName vs rename) and knows the is-prefix accessor rules.
Anticipates framework introspection impact when renaming accessors and chooses the least disruptive fix.
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)