skip to content

A Kotlin class has `val isActive: Boolean` and `val enabled: Boolean`. What getter names does Java see, and what subtle interop pitfall can the `is` prefix cause?

level: seniorimportance: nice to knowfreq 25%

answer

  1. Boolean getter uses is-prefix: enabled -> isEnabled()
  2. isActive stays isActive() (not doubled)
  3. var setter drops is: setActive()
  4. Introspectors may strip is -> property maps to 'active'
  5. Only primitive Boolean; Boolean? uses getX()

basics

~20 s

For a boolean property whose name already starts with is, Kotlin keeps that name as the getter (isActive()). For other boolean properties it adds is, so enabled gets isEnabled(). Mismatched expectations can break frameworks that look for getEnabled().

solid answer

~40 s

Kotlin uses an `is`-prefix convention for `Boolean` getters. A property named `isActive: Boolean` keeps its name: getter `isActive()`, and a `var` setter `setActive(...)` (the `is` is stripped on the setter). A property named `enabled: Boolean` gets getter `isEnabled()`. The pitfall: some Java frameworks/serializers (Jackson, certain bean introspectors) infer the property name from the accessor and may map `isActive()` to a JSON/bean property called `active`, dropping the `is`. So a Kotlin field `isActive` can round-trip to/from JSON as `active`, causing silent mapping mismatches. You can force a stable name with `@get:JvmName("getIsActive")` or `@JsonProperty`. Also note: this `is` convention applies only to `Boolean` (not `Boolean?`, which uses the regular `getX()` form because it is a boxed `Boolean`).

code

kotlin · 6 lines
kotlin
class Flags {
    val isActive: Boolean = true   // isActive()
    val enabled: Boolean = false   // isEnabled()
    @get:JvmName("getIsActive")
    val pinned: Boolean = true      // forces getIsActive() to dodge is-stripping
}

go deeper

for a junior

Knows boolean getters use an is-prefix (isEnabled()).

for a middle

Knows isActive stays isActive() and the var setter drops the is (setActive()).

for a senior

Explains the introspector name-stripping pitfall and that the rule is for primitive Boolean only.

for a principal

Sets a codebase convention and boundary policy (@get:JvmName / serializer annotations) to keep wire/bean names stable across Java and JSON consumers.

## The `is` convention Kotlin maps `Boolean` property accessors using an `is` prefix instead of `get`: - `val ok: Boolean` -> getter `isOk()`. - `val isReady: Boolean` -> getter `isReady()` (the name already starts with `is`, so it is not doubled into `isIsReady`). - For a `var isReady: Boolean`, the setter drops the `is`: `setReady(boolean)`. ```kotlin class Flags { val isActive: Boolean = true // Java: isActive() val enabled: Boolean = false // Java: isEnabled() var isOpen: Boolean = false // Java: isOpen() / setOpen(boolean) } ``` ## Only for primitive `Boolean` The `is` form applies to the **non-null primitive `Boolean`**. A nullable `Boolean?` is a boxed `java.lang.Boolean` and uses the ordinary `getX()` form (e.g. `val flag: Boolean?` -> `getFlag()`), because the JavaBeans `is`-prefix rule classically applies to primitive booleans. ## The interop pitfall Java bean introspectors and JSON libraries reconstruct the **logical property name** from accessor names. Given `isActive()`, an introspector may decide the property is named `active` (it strips the `is` just as it strips `get`). Consequences: - A serializer can emit JSON key `active` for a Kotlin field you named `isActive` — or fail to bind incoming `isActive` keys. - Two Kotlin properties `active` and `isActive` could both map to logical name `active` and collide. - A framework expecting `getEnabled()` (literal) won't find it because Kotlin generated `isEnabled()`. ## Forcing a stable accessor name Use `@JvmName` on the accessor to pin the JVM method name: ```kotlin class Flags { @get:JvmName("getIsActive") val isActive: Boolean = true // Java: getIsActive() } ``` Or annotate for the serializer directly (e.g. Jackson's `@JsonProperty("isActive")`) to control the wire name. Pick one consistent strategy across the codebase. ## Practical guidance - Decide on a naming style for boolean properties early. - Be explicit with `@get:JvmName` or serializer annotations at the Java/JSON boundary where the `is` stripping bites. - Remember the rule only fires for non-null primitive `Boolean`.

  • Why might `val isActive: Boolean` serialize to JSON key `active`?
    Bean/JSON introspectors derive the property name from the accessor by stripping the verb prefix, treating `isActive()` as property `active`.
  • Does `val flag: Boolean?` get `isFlag()` or `getFlag()`?
    `getFlag()`, because a nullable Boolean is a boxed java.lang.Boolean, so the is-prefix convention does not apply.

saying these in an interview costs you the question

  • Saying every Boolean property gets getX() like other types
  • Thinking isActive becomes getIsActive() by default
  • Claiming Boolean? also uses the is-prefix
  • Ignoring the serializer/bean name-stripping pitfall
  • Not knowing @get:JvmName can pin the accessor name

context