Skip to content
Lesson 4 of 19

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() and toLowerCase() to uppercase() and lowercase(). 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 writeYou getWhy
"$name"Adaa plain name needs no braces
"$name.length"Ada.lengththe name stops at name; .length is just text
"${name.length}"3braces let the whole expression run
"${'$'}5.00"$5.00this 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

CallResult for "ship that code"
.length14
.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.

Up nextNull SafetyStrings and Null Safety

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…