skip to content

What does the stdlib `use` function do, and why is it preferred over manually calling `close()` on a resource?

level: juniorimportance: must knowfreq 70%

answer

  1. inline extension on Closeable/AutoCloseable
  2. close() in finally, always
  3. addSuppressed keeps original error
  4. Kotlin's try-with-resources
  5. returns the lambda's value

basics

~10 s

use runs your code with a resource like a file, then automatically closes it afterward, even if an error happens. It saves you from forgetting to close it yourself.

solid answer

~40 s

`use` is an inline extension function on `Closeable`/`AutoCloseable`. You write `reader.use { r -> ... }`; it executes the lambda, then guarantees `close()` is called in a `finally` block whether the block returns normally or throws. This is Kotlin's equivalent of Java's try-with-resources. If the block throws and `close()` also throws, the close exception is added as a suppressed exception on the original (via `addSuppressed`), so the original error is not lost. Because `use` is `inline`, the lambda body is inlined at the call site with no extra object allocation. The return value of `use` is whatever the lambda returns, so you can compute and return a result directly: `val text = file.bufferedReader().use { it.readText() }`. Always prefer it over manual `try/finally { close() }`.

code

kotlin · 2 lines
kotlin
val lines: List<String> = File("in.txt").bufferedReader().use { it.readLines() }
// reader is closed here, even if readLines() throws

go deeper

for a junior

Knows use auto-closes the resource and replaces manual close().

for a middle

Explains the finally semantics and that use returns the lambda value.

for a senior

Discusses addSuppressed, inline (no allocation), and the AutoCloseable overload.

for a principal

Frames use as the stdlib's deliberate mapping of try-with-resources onto an inline function, and reasons about exception-masking guarantees in library APIs.

## What `use` is `use` is a standard-library **extension function** declared (roughly) as `inline fun <T : Closeable?, R> T.use(block: (T) -> R): R`. There is also an overload for `AutoCloseable`. It models **scoped resource management**: a resource is acquired, used inside a block, then deterministically released. ## Why it exists Files, sockets, streams, and database connections hold OS-level handles that must be released. If you forget to call `close()`, you leak handles. Manual `try/finally` is verbose and easy to get wrong (e.g. swallowing the real exception). `use` packages the correct pattern once. ## How it works internally Conceptually: ```kotlin inline fun <T : Closeable?, R> T.use(block: (T) -> R): R { var exception: Throwable? = null try { return block(this) } catch (e: Throwable) { exception = e throw e } finally { when { this == null -> {} exception == null -> this.close() else -> try { this.close() } catch (closeEx: Throwable) { exception.addSuppressed(closeEx) } } } } ``` Key points: - **`finally`** guarantees `close()` runs on normal return *and* on exception. - If the block threw and `close()` *also* throws, the close exception is attached with **`addSuppressed`** so the primary failure is preserved. You can see it later via `Throwable.suppressed`. - It is **`inline`**, so the lambda is inlined — no `Function` object is allocated and `return`/`break` behave naturally. ## Typical usage ```kotlin val text = File("data.txt").bufferedReader().use { reader -> reader.readText() } ``` The value of the `use` expression is the lambda's last expression, so you can return computed data straight out of it. ## Relationship to Java This is Kotlin's counterpart to Java's **try-with-resources**. Kotlin chose a library function (`use`) plus lambdas instead of dedicated syntax, which is a recurring theme in the stdlib: runtime concepts are mapped onto inline functions rather than new keywords.

  • What happens if both the block and close() throw?
    The block's exception propagates; the close() exception is attached to it via addSuppressed and retrievable from Throwable.suppressed.
  • Can use return a value?
    Yes — use returns whatever the lambda returns, so you can compute and return a result directly.

Like a self-locking door: you walk through, do your thing, and it locks behind you no matter how you leave.

saying these in an interview costs you the question

  • Claiming use only works on files
  • Saying you still need a manual finally with use
  • Thinking close() runs only on success, not on exception
  • Believing the close exception overwrites/hides the original error
  • Not knowing use returns the lambda result

context