skip to content

What are Kotlin string templates, and what is the difference between the $name and ${expression} forms?

level: juniorimportance: must knowfreq 80%

answer

  1. $name = one identifier only
  2. ${...} = any expression
  3. always calls toString()
  4. null renders as "null"
  5. dot/call/index needs braces

basics

~10 s

String templates let you put values inside a string. Use $name to insert a variable, and ${...} to insert a whole expression. Kotlin replaces them with the text of the value.

solid answer

~40 s

A string template is a string literal containing template expressions evaluated at runtime and spliced into the result. The short form `$name` references a single identifier (a simple variable name). The braced form `${expression}` evaluates any arbitrary Kotlin expression — property access, method calls, arithmetic — and inserts its result. Both convert the value to text by calling `toString()` on it (with `null` rendered as the string "null"). The short form only works for a bare identifier; the moment you need a dot, call, index, or operator you must use braces, e.g. `${user.name}`, `${list.size}`, `${a + b}`. Templates work the same in regular double-quoted strings and in raw (triple-quoted) strings.

code

kotlin · 4 lines
kotlin
val user = "Ada"
val scores = listOf(90, 85)
println("$user scored ${scores.average()} on ${scores.size} tests")
// Ada scored 87.5 on 2 tests

go deeper

for a junior

Knows $name vs ${expression} and that values become text.

for a middle

Explains that toString() is called, null renders as "null", and why dots/calls need braces.

for a senior

Notes the compiler lowers templates to concatenation/StringBuilder, so there is no runtime cost versus manual concatenation.

for a principal

Can discuss readability/maintainability trade-offs of heavy interpolation vs extracted variables, and locale concerns when toString() formats numbers.

## What a string template is A **string template** is a string literal that contains one or more **template expressions** — placeholders that Kotlin evaluates at runtime and substitutes into the final string. This is Kotlin's form of *string interpolation*. There are two syntactic forms: - **Short form `$name`** — a `$` immediately followed by a single identifier (a variable or parameter name). It inserts the value of that one identifier and nothing more. It stops at the first character that can't be part of an identifier. - **Braced form `${expression}`** — a `$` followed by `{ ... }` containing **any** valid Kotlin expression. Use this whenever you need more than a bare name: property access (`${user.name}`), function calls (`${name.uppercase()}`), indexing (`${list[0]}`), arithmetic (`${a + b}`), or even an `if`/`when` expression. ## How the value is rendered Every template expression's result is converted to a `String` by calling **`toString()`** on it. For a `null` value the literal text `"null"` is produced (Kotlin handles this safely; it does not throw). So `"x = ${obj}"` is effectively `"x = " + obj.toString()`. ## When braces are required ```kotlin val name = "Ada" val list = listOf(1, 2, 3) println("Hi $name") // short form: Hi Ada println("Len: ${list.size}") // braces needed for the .size call println("First: ${list[0]}") // braces needed for indexing println("$name has ${list.size} items") ``` Without braces, `"$list.size"` would print the whole list's `toString()` followed by the literal text `.size`, because the short form captures only the identifier `list` and treats `.size` as ordinary characters. ## Compilation note The compiler lowers templates to string concatenation / `StringBuilder` calls; templates are not a runtime reflection feature. There is no performance penalty versus writing the concatenation by hand. ## Same behavior in raw strings Templates behave identically inside triple-quoted (raw) strings — `$name` and `${...}` are interpolated there too — the only difference is that raw strings don't process backslash escapes.

  • What does "$list.size" print if list is listOf(1,2,3)?
    It prints the list's toString() ("[1, 2, 3]") followed by the literal ".size", i.e. "[1, 2, 3].size" — the short form only captured the identifier list.
  • What happens when the interpolated value is null?
    Kotlin renders it as the four-character string "null"; it does not throw a NullPointerException.

Like a fill-in-the-blanks form: $name fills one blank with a single field, ${...} lets you compute the answer before filling the blank.

saying these in an interview costs you the question

  • Thinks $name can include a method call like $name.length
  • Believes templates use reflection or are slow
  • Says null causes an exception in a template
  • Confuses ${} with format specifiers like %s
  • Thinks templates only work in regular strings, not raw strings

context