Step 1 of 5 · Reading · ~3 min
Learn
Strings and Null Safety
Strings and String Templates
A Kotlin String is immutable. Nothing you call on it changes it — every operation hands back a
brand-new string and leaves the original exactly as it was.
fun main() {
val greeting = "hello"
val loud = greeting.toUpperCase()
println(greeting)
println(loud)
println(greeting.length)
println(greeting.contains("ell"))
}
//> hello
//> HELLO
//> 5
//> true
greeting is still hello after the call. If you want the uppercase version, you have to keep
the value that came back.
Naming note: Kotlin 1.5 renamed
toUpperCase()andtoLowerCase()touppercase()andlowercase(). The old names work on every version; the new ones only exist on 1.5 and later. When you are unsure which compiler your code will meet, the old names are the safe choice.
String templates
Instead of gluing strings together with +, you drop values straight into the text. A $
followed by a name inserts that value.
fun main() {
val name = "Ada"
val age = 36
println("$name is $age years old")
println("Next year she is ${age + 1}")
}
//> Ada is 36 years old
//> Next year she is 37
A bare $name works for a plain variable. Anything more — a calculation, a method call, an
index — has to go inside braces as ${...}.
When do I need the braces?
| You write | You get | Why |
|---|---|---|
"$name" | Ada | a plain name needs no braces |
"$name.length" | Ada.length | the name stops at name; .length is just text |
"${name.length}" | 3 | braces let the whole expression run |
"${'$'}5.00" | $5.00 | this is how you print a literal dollar sign |
The second row is the one that bites, because it is not an error. The program compiles happily and prints something that looks almost right.
✓ Correct:
println("The name has ${name.length} letters")
✗ Compiles, prints nonsense:
println("The name has $name.length letters")
Output of the wrong version:
The name has Ada.length letters
Raw strings
Triple quotes hold text exactly as written: real line breaks, and no escape processing.
fun main() {
val block = """
line one
line two
""".trimIndent()
println(block)
}
//> line one
//> line two
trimIndent() removes the shared leading whitespace, so you can indent the literal to match the
code around it without those spaces ending up in the output. Raw strings still run templates,
which is why a literal dollar sign inside one is written ${'$'}.
String calls you will keep reaching for
| Call | Result for "ship that code" |
|---|---|
.length | 14 |
.trim() | removes surrounding whitespace |
.split(" ") | [ship, that, code] |
.substring(0, 4) | ship |
.replace("code", "kotlin") | ship that kotlin |
.isEmpty() | false |
Because every one of these returns a new string, they chain: line.trim().split(" ") is a
perfectly ordinary thing to write.
Your exercise
Greeting Card reads a name on the first line and an age on the second, then prints one line in a fixed format.
The starter has already read both values; your job is to build the line with a template. The
mistake the grader catches most often is copying the placeholder braces out of the description
literally — printing Hi, {name}! — because Kotlin has no idea what {name} means and prints
it as plain text. The second most common failure is spacing: the test compares character for
character, so Hi, Alice ! with a space before the exclamation mark fails, and so does dropping
the full stop at the end.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…