skip to content

Property & Constructor References

Property references give you a KProperty with get and set, and ::ClassName gives you the constructor as a factory function. Passing a constructor reference to map is the idiom worth having ready.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What is a property reference like ::name or Person::name in Kotlin, and what can you do with the value you get?

level: juniorimportance: must knowfreq 55%

answer

  1. :: makes a property a value, not its value
  2. Type::prop is KProperty1 and acts as (T) -> R
  3. .get / .set / .name on the reference
  4. var gives KMutableProperty with .set
  5. people.map(Person::name)

basics

~10 s

It is a value that points to a property instead of reading it. You can pass it to functions like map to read that property from many objects, for example people.map(Person::name).

solid answer

~30 s

A property reference uses the :: operator to refer to a property as a first-class object instead of accessing its value. Person::name yields a KProperty1<Person, String> (a function-like object). Calling it with a Person returns that person's name, so it works as a (Person) -> String, ideal for people.map(Person::name). For a property in scope, ::count gives a KProperty0. The reference also exposes metadata: .name returns the property's name as a String, and .get(receiver) reads the value. If the property is a var, mutable reference types (KMutableProperty1) also expose .set(receiver, value).

code

kotlin · 4 lines
kotlin
data class User(val email: String)
val users = listOf(User("[email protected]"), User("[email protected]"))
val emails = users.map(User::email) // [[email protected], [email protected]]
println(User::email.name)            // "email"

go deeper

for a junior

Knows ::prop is a value and can use Person::name in map.

for a middle

Names KProperty1, knows .get/.name and that var yields a mutable reference.

for a senior

Distinguishes KProperty0/1, mutable vs read-only, and how it acts as a function type.

for a principal

Frames it as kotlin.reflect first-class members enabling type-safe generic field access in libraries.

## What a property reference is A **property reference** is created with the **`::` (double-colon) operator** and refers to a Kotlin **property** as a first-class object you can store, pass, and call — rather than reading its current value. `Person::name` does not read a name; it produces an object representing the `name` property of `Person`. ## The type you get: KProperty The reference's type comes from the **`kotlin.reflect`** hierarchy: - `Person::name` (unbound, on a type) → **`KProperty1<Person, String>`** — a property with one receiver. It is also a function `(Person) -> String`. - `::topLevelOrLocalProp` (no receiver) → **`KProperty0<String>`** — call it with `()`. - A reference to a `var` adds a setter: **`KMutableProperty1`** / **`KMutableProperty0`**, exposing `.set(...)`. ## Why it doubles as a function `KProperty1<T, R>` implements the function type `(T) -> R` via its `invoke`/`get`, so it can be passed anywhere a lambda of that shape is expected: ```kotlin data class Person(val name: String, var age: Int) val people = listOf(Person("Ada", 36), Person("Linus", 54)) val names: List<String> = people.map(Person::name) // [Ada, Linus] // Reflection API on the same reference: val ref = Person::name println(ref.name) // "name" (metadata) println(ref.get(people[0])) // "Ada" val ageRef = Person::age // KMutableProperty1<Person, Int> ageRef.set(people[0], 99) // requires var ``` ## Key APIs - **`.get(receiver)`** — read the value. - **`.set(receiver, value)`** — write (only on `KMutableProperty*`). - **`.name`** — the property's source name as a `String`. - **`.invoke(receiver)`** / calling it like a function — same as `get`. ## Common uses - `map`, `sortedBy`, `groupBy`, `associateBy` with `Type::prop`. - Building generic, type-safe "get this field" logic without writing lambdas.

  • What is the difference between Person::name and ::name?
    Person::name is unbound (KProperty1, needs a Person receiver). ::name refers to a property in the current scope (KProperty0), called with no receiver.

Like handing someone a labelled measuring tool ('the name field') instead of a single measurement you already took.

saying these in an interview costs you the question

  • Saying Person::name reads/returns the name value immediately
  • Claiming it only works inside reflection and cannot be passed to map
  • Not knowing it has a usable .name or .get
  • Thinking it needs an instance to be written (Person::name vs p::name)

context

open as a page

How does a constructor reference (::ClassName) work, and how would you use it as a factory passed to map?

level: middleimportance: must knowfreq 50%

basics

~20 s

::ClassName is a value that creates new objects of that class. Its parameters match the constructor, so you can pass it where a function is expected, like ids.map(::User) to turn each id into a User.

open as a page

Using a property reference's reflection surface, how do you read a name, read a value, and mutate a property — and what types make set available?

level: middleimportance: should knowfreq 40%

basics

~10 s

On a property reference you can call .name to get the property's name, .get(obj) to read its value, and .set(obj, value) to change it. Only references to var properties (mutable ones) allow .set.

open as a page

Show how property references combine with collection operators (sortedBy, groupBy, associateBy, maxByOrNull) and explain what happens at the type level.

level: middleimportance: should knowfreq 38%

basics

~10 s

Many collection functions take a 'selector' function that returns a value per item. A property reference like Person::age fits perfectly: people.sortedBy(Person::age) sorts by age, people.groupBy(Person::city) groups by city.

open as a page

When should you prefer Type::prop or ::ClassName over an equivalent lambda, and what are the trade-offs and pitfalls?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Use references when the lambda would just call one property or constructor (Person::name instead of { it.name }). They are shorter and clearer. Use a lambda when you need extra logic, defaults, or to control which overload is called.

open as a page