skip to content

Callable References (::fn, ::prop)

A :: reference is both a callable value and a reflection object, so String::length can be passed to map and also inspected. That dual nature is what makes references more interesting than lambdas.

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

questions

5

What is a callable reference in Kotlin, and how do you write a reference to a top-level function, a member function, and a property?

level: juniorimportance: must knowfreq 70%

answer

  1. :: = "point at", don't call
  2. ::fn top-level, Class::m unbound, obj::m bound
  3. String::length has type (String) -> Int
  4. Result is KFunction/KProperty (a KCallable)
  5. Replaces trivial lambdas in map/filter

basics

~10 s

A callable reference points at an existing function or property by name using the :: operator, so you can pass it around instead of writing a lambda. Example: list.map(String::length).

solid answer

~30 s

A callable reference uses the :: operator to grab an existing declaration as a value instead of calling it. ::topLevelFun references a top-level function; String::length references a member (here a property) on the class; obj::method binds to a specific instance. The result is a function-typed object (KFunction/KProperty) you can pass where a lambda is expected, e.g. names.map(String::uppercase) or list.filter(::isValid). It avoids the boilerplate lambda { it.uppercase() } and reads more declaratively. The reference's type matches the underlying signature, so String::length has type (String) -> Int. References also implement KCallable, so they double as reflection handles.

code

kotlin · 6 lines
kotlin
fun shout(s: String) = s.uppercase() + "!"
val words = listOf("hi", "yo")

val a = words.map(::shout)        // top-level fun ref
val b = words.map(String::uppercase) // unbound member ref, (String)->String
val c: () -> Int = "hello"::length   // bound member ref

go deeper

for a junior

Knows :: makes a reference, can use String::length in map and pass ::topLevelFun where a lambda is expected.

for a middle

Distinguishes unbound vs bound and states the resulting function type precisely.

for a senior

Connects references to KFunction/KProperty/KCallable and knows the stdlib-vs-kotlin-reflect line for plain use vs introspection.

for a principal

Frames references as the bridge between Kotlin's functional-value model and its reflection model and reasons about API design implications of accepting references.

## What a callable reference is A **callable reference** turns an existing function or property into a **value** you can pass around, instead of *calling* it. You create one with the **`::` operator**. Think of it as "point at this declaration" rather than "invoke this declaration". ## The three common forms ```kotlin // 1. Top-level (or local) function reference — nothing before :: fun isOdd(x: Int) = x % 2 == 1 val refs = listOf(1, 2, 3).filter(::isOdd) // ::isOdd has type (Int) -> Boolean // 2. Member reference on a CLASS — ClassName::member (unbound) val lengths = listOf("a", "bb").map(String::length) // (String) -> Int // 3. Member reference on an INSTANCE — instance::member (bound) val s = "hello" val getLen: () -> Int = s::length // already bound to s, no String param ``` ## Why use them - **Less boilerplate** than a lambda: `String::uppercase` vs `{ s -> s.uppercase() }`. - **Declarative**: the name documents intent. - They satisfy any **function type** parameter (`(T) -> R`), so they slot into `map`, `filter`, `let`, etc. ## What you actually get back The `::` expression produces an object implementing **`KFunction`** (for functions) or **`KProperty`** (for properties), both of which extend **`KCallable`**. So a reference is simultaneously: - usable as a **function** (you can `invoke()` / call it), and - a **reflection handle** (it has `.name`, `.parameters`, etc.). Basic function-as-value usage (calling it) works with only the standard library. Deeper reflection on it (reading `.name`, `.parameters`) needs the **`kotlin-reflect`** artifact at runtime. ## Quick mental model `obj.method()` = call now. `obj::method` = a thing I can call later.

  • What type does String::length have?
    (String) -> Int — it's an unbound reference, so the receiver becomes the first parameter.
  • Do you need kotlin-reflect just to pass String::uppercase to map?
    No. Using a reference as a plain function value works with the stdlib alone; kotlin-reflect is only needed to introspect it (read name, parameters, etc.).

A lambda is writing a sticky note 'go do X'; a callable reference is just handing someone the phone number of the function that already does X.

saying these in an interview costs you the question

  • Confusing :: with calling — saying obj::method() runs the method now
  • Thinking ::fn returns the function's return value instead of a function object
  • Believing every callable reference always requires kotlin-reflect
  • Not knowing the receiver becomes a parameter in an unbound reference

context

open as a page

Explain the difference between a bound and an unbound callable reference, including how their function types differ.

level: middleimportance: must knowfreq 60%

basics

~10 s

Unbound references name a member on a class (Class::m) and take the receiver as a parameter. Bound references fix a specific object (obj::m), so the receiver is baked in and not a parameter.

open as a page

Show how constructor references (::ClassName) and mutable-property references work, including using a property reference to both read and write a field reflectively.

level: middleimportance: should knowfreq 35%

basics

~10 s

::ClassName references a constructor and acts like a factory function. A property reference to a var lets you read it with get and change it with set, because it is a KMutableProperty.

open as a page

How does Kotlin resolve which function an overloaded callable reference like ::println points to, and how do you disambiguate?

level: seniorimportance: should knowfreq 30%

basics

~20 s

When a name is overloaded, the compiler picks the overload by looking at the expected function type from the context. If that isn't enough, you add an explicit type to tell it which one you mean.

open as a page

A callable reference is both a function value and a reflection handle. What reflective information can you read off it, and what runtime dependency does that require?

level: seniorimportance: should knowfreq 45%

basics

~10 s

A reference object also exposes metadata like its name and parameters because it's a KCallable. Reading that metadata at runtime needs the kotlin-reflect library on the classpath; just calling the reference does not.

open as a page