skip to content

What does it mean that functions are 'first-class' in Kotlin, and how does that differ from how Java traditionally modeled functions?

level: juniorimportance: must knowfreq 70%

answer

  1. Value: store, pass, return
  2. Function type (Int) -> String is real
  3. Lambda / anonymous fun / :: reference
  4. Higher-order = takes/returns a function
  5. Java pre-8 needed SAM interface

basics

~20 s

First-class means a function is a value: you can store it in a variable, pass it to another function, and return it. In Kotlin you do this directly; old Java needed an interface or anonymous class wrapper.

solid answer

~40 s

In Kotlin a function is a value with a function type like `(Int) -> String`. You can assign it to a `val`, pass it as an argument, or return it. You produce these values with lambdas `{ x -> ... }`, anonymous functions `fun(x: Int) = ...`, or function references `::name` / `String::length`. Higher-order functions take or return such values. Java historically had no function values: you simulated them with single-method interfaces (later `@FunctionalInterface` + lambdas in Java 8). Kotlin bakes function types into the type system, so `(Int) -> String` is a real type, not just sugar over an interface. Under the hood the compiler still represents these as `FunctionN` interface instances on the JVM, but the language treats them as ordinary values.

code

kotlin · 6 lines
kotlin
fun applyTwice(x: Int, op: (Int) -> Int): Int = op(op(x))

val inc: (Int) -> Int = { it + 1 }
println(applyTwice(3, inc))        // 5
println(applyTwice(3, ::square))   // 81  (function reference)
fun square(n: Int) = n * n

go deeper

for a junior

Can state the store/pass/return definition and write a lambda assigned to a val.

for a middle

Distinguishes lambdas, anonymous functions, and references; uses higher-order functions like map.

for a senior

Explains the FunctionN JVM representation and contrasts with Java functional interfaces and SAM conversion.

for a principal

Discusses inlining to erase the FunctionN allocation, API design with function-type parameters, and interop tradeoffs.

## What 'first-class' means A value is **first-class** in a language if it can be: stored in a variable, passed as an argument, and returned from a function. In Kotlin, **functions are first-class values** — they sit alongside `Int`, `String`, etc. ## Function types Kotlin has dedicated **function types** written as `(ParamTypes) -> ReturnType`. Examples: - `() -> Unit` — takes nothing, returns `Unit` (Kotlin's `void`-like type). - `(Int, Int) -> Int` — takes two `Int`s, returns an `Int`. - `(String) -> Boolean` — a predicate. A variable can hold one: ```kotlin val add: (Int, Int) -> Int = { a, b -> a + b } val result = add(2, 3) // invoke like a normal function -> 5 ``` ## Ways to create a function value - **Lambda**: `{ a, b -> a + b }` — an anonymous function expression. - **Anonymous function**: `fun(a: Int, b: Int): Int = a + b` — like a lambda but allows explicit return type and `return`. - **Function reference** with `::` — `::println`, `String::length`, `instance::method`. ## Higher-order functions A **higher-order function** takes a function as a parameter and/or returns one. This is what makes `map`, `filter`, `forEach` possible: ```kotlin fun <T> List<T>.myFilter(keep: (T) -> Boolean): List<T> { /* ... */ } listOf(1, 2, 3).myFilter { it > 1 } // pass a predicate value ``` ## Contrast with traditional Java Before Java 8, Java had no function values. You emulated them with a **single-abstract-method interface** (e.g. `Runnable`, `Comparator`) and an anonymous class. Java 8 added lambdas, but they are still typed as **functional interfaces** — there is no standalone `(Int) -> String` type. Kotlin makes the function type a real, named-by-shape type in the type system. ## On the JVM Kotlin compiles a function value to an instance of a generated `FunctionN` interface (`Function0`, `Function1`, ... with an `invoke` method). So interop is smooth, but you write and reason about it as a plain value — that is the first-class part.

  • What concrete JVM type does a Kotlin lambda compile to?
    An instance of a generated FunctionN interface (Function0, Function1, ...) whose single `invoke` method holds the body.
  • Name three ways to obtain a function value in Kotlin.
    A lambda `{ ... }`, an anonymous function `fun(...) {...}`, and a function reference like `::foo` or `String::length`.

A function value is like a recipe card you can hand to someone, file away, or get back — not a meal you can only eat in place.

saying these in an interview costs you the question

  • Claiming Kotlin lambdas are 'just syntax' with no underlying type
  • Saying you cannot store a function in a variable
  • Confusing function type (Int)->String with a generic class
  • Thinking only methods inside classes can be passed around
  • Asserting Java always had first-class functions

context