When working with Kotlin, you’ll often come across constructor references and function references. At first glance, they may look similar, but they serve different purposes. Understanding the difference between them will help you write cleaner, more expressive, and more reusable code.
This post will break it down in a simple way with examples, so you’ll know exactly when to use constructor references and function references.
What Are Function References in Kotlin?
A function reference lets you refer to a function by its name, without calling it directly. Instead of executing the function, Kotlin treats it as a value that can be passed around.
fun greet(name: String) {
println("Hello, $name!")
}
fun main() {
val greeter: (String) -> Unit = ::greet
greeter("Kotlin") // Prints: Hello, Kotlin!
}
Here,
::greet
is a function reference.- We’re not calling
greet()
directly. Instead, we’re passing the reference intogreeter
. - Later, we call it with
greeter("Kotlin")
.
This is especially useful when working with higher-order functions like map
, filter
, or custom callbacks.
What Are Constructor References in Kotlin?
A constructor reference points to a class constructor instead of a function. This allows you to create new instances of a class without explicitly calling ClassName()
.
data class User(val name: String)
fun main() {
val users = listOf("amol", "akshay", "rahul")
val userObjects = users.map(::User)
println(userObjects)
// Output: [User(name=amol), User(name=akshay), User(name=rahul)]
}
::User
is a constructor reference.- Instead of writing
users.map { User(it) }
, we simply pass::User
. - Kotlin automatically knows that
::User
matches the expected function type(String) -> User
.
This makes your code shorter and more expressive, especially when working with collections.
Constructor References vs Function References: Key Differences
Now let’s compare them side by side.

Example
Imagine you’re processing a list of numbers and converting them into Result
objects.
data class Result(val value: Int)
fun square(n: Int): Int = n * n
fun main() {
val numbers = listOf(2, 4, 6)
// Using function reference
val squared = numbers.map(::square)
// Using constructor reference
val results = squared.map(::Result)
println(results)
// Output: [Result(value=4), Result(value=16), Result(value=36)]
}
What’s happening here?
::square
is a function reference that transforms each number.::Result
is a constructor reference that wraps each transformed number into an object.
This example highlights how constructor references and function references complement each other.
When to Use Which
- Use function references when you want to pass existing logic around. For example, reusing a utility function inside a higher-order function.
- Use constructor references when you need to create objects dynamically, especially inside collection transformations.
Avoiding Ambiguity: Overloaded Functions and Constructors
Kotlin allows overloaded functions and constructors. When using references, the compiler needs to know which version to pick, so you often provide explicit type information to resolve ambiguity:
fun add(a: Int, b: Int) = a + b
fun add(a: Double, b: Double) = a + b
val intAdder: (Int, Int) -> Int = ::add // Unambiguous because of type
Conclusion
At first, constructor references and function references may seem confusing because the syntax looks similar. But once you know the difference, it’s clear:
- Function references point to reusable logic.
- Constructor references point to object creation.
Both are powerful tools that make Kotlin code more expressive, concise, and elegant. By mastering them, you’ll write cleaner and more functional-style Kotlin programs.