skip to content

What do the built-in `name` and `ordinal` properties of an enum constant return, and what should you be careful about with `ordinal`?

level: middleimportance: must knowfreq 65%

answer

  1. name = declared identifier String
  2. ordinal = zero-based declaration index
  3. both are final, inherited from kotlin.Enum
  4. never persist ordinal — reorder breaks it
  5. compareTo/sorting use ordinal

basics

~10 s

name gives the constant's declared identifier as a String (e.g. "RED"). ordinal gives its zero-based position in the declaration list (0, 1, 2...). Be careful: reordering constants changes every ordinal.

solid answer

~40 s

Every enum constant inherits two read-only properties from `kotlin.Enum`: `name: String` is the exact identifier you wrote (`Color.RED.name == "RED"`), and `ordinal: Int` is its zero-based index in declaration order (`Color.RED.ordinal == 0`). Both are `val`. `ordinal` is fragile: it is derived purely from declaration order, so inserting or reordering constants silently shifts ordinals — never persist `ordinal` to a database or wire format, prefer `name` (stable as long as you don't rename). `toString()` defaults to `name` but can be overridden, so use `name` when you need the guaranteed identifier. Enums also implement `Comparable` using `ordinal`, so `compareTo` and sorting follow declaration order. `name`/`ordinal` are final and cannot be overridden.

code

kotlin · 5 lines
kotlin
enum class Priority { LOW, MEDIUM, HIGH }

println(Priority.MEDIUM.name)    // "MEDIUM"
println(Priority.MEDIUM.ordinal) // 1
println(Priority.HIGH > Priority.LOW) // true (ordinal-based compareTo)

go deeper

for a junior

Knows name returns the identifier String and ordinal the position index.

for a middle

Understands ordinal fragility and prefers name for persistence; knows both are final.

for a senior

Explains name vs toString, ordinal-based Comparable, and safe persistence via explicit ids.

for a principal

Sets team conventions/serialization contracts that forbid ordinal persistence and handle enum evolution safely.

## The two inherited properties Every Kotlin enum constant inherits from the abstract base class `kotlin.Enum<E>` two read-only (`val`) properties: ```kotlin enum class Color { RED, GREEN, BLUE } Color.RED.name // "RED" (String) Color.RED.ordinal // 0 (Int) Color.GREEN.ordinal // 1 Color.BLUE.ordinal // 2 ``` ### `name: String` - Returns the **exact declared identifier** of the constant as text. - It is the inverse of `valueOf`: `Color.valueOf("RED") === Color.RED` and `Color.RED.name == "RED"`. - It is **final** — you cannot override it. - It changes only if you **rename** the constant in source. ### `ordinal: Int` - Returns the **zero-based position** of the constant in the declaration list. - The first constant is `0`, the next `1`, and so on. - It is **final** and is the basis for the enum's `Comparable` implementation. ## Why `ordinal` is dangerous to persist `ordinal` is **derived from source order**, not from any stable identity. If you later insert a new constant in the middle or reorder them, **every following ordinal shifts**: ```kotlin // v1 enum class Status { NEW, DONE } // NEW=0, DONE=1 // v2 — someone inserts IN_PROGRESS enum class Status { NEW, IN_PROGRESS, DONE } // NEW=0, IN_PROGRESS=1, DONE=2 (!) ``` Any stored value `1` that previously meant `DONE` now decodes as `IN_PROGRESS` — silent data corruption. **Rule of thumb:** for databases, JSON, or any external format, persist **`name`** (stable across reorders) or an explicit, hand-assigned id you store as a constructor parameter — never `ordinal`. ## `name` vs `toString()` By default `toString()` returns `name`, but `toString()` **can be overridden** in the enum body. So when you need the guaranteed declared identifier (for serialization or lookups), use **`name`**, not `toString()`. ## Comparability Because enums implement `Comparable<E>` using `ordinal`, `compareTo`, sorting, and `minOf`/`maxOf` follow **declaration order**: ```kotlin enum class Priority { LOW, MEDIUM, HIGH } listOf(Priority.HIGH, Priority.LOW).sorted() // [LOW, HIGH] ```

  • Why prefer name over ordinal for database storage?
    ordinal depends on declaration order; inserting/reordering constants silently changes it and corrupts stored data. name only changes on an explicit rename.
  • Is `toString()` always equal to `name`?
    By default yes, but `toString()` can be overridden in the enum, while `name` is final and always returns the declared identifier.
  • Can you override `ordinal` to control sort order?
    No — `ordinal` is final. To customize ordering, implement a Comparator or store an explicit rank as a constructor parameter.

name is a person's name; ordinal is their seat number in a row — renumber the seats and the same person gets a different number.

saying these in an interview costs you the question

  • Persisting `ordinal` to a DB or message format
  • Assuming `ordinal` is stable across versions
  • Using `toString()` for serialization instead of `name`
  • Claiming `name` or `ordinal` can be overridden
  • Not knowing enum comparison is based on declaration order

context