Question
What is the correct way to concatenate strings in Kotlin?
In Java, you can use String.concat():
String a = "Hello ";
String b = a.concat("World"); // "Hello World"
Kotlin does not expose concat() in the same way. Should string concatenation be done with the + operator?
Short Answer
You will learn how Kotlin joins strings with the + operator, how string templates make values easier to embed in text, and when StringBuilder is a better choice for repeated concatenation.
Concept
Kotlin commonly concatenates strings with the + operator:
val message = "Hello " + "World"
The result is a new string, "Hello World".
Kotlin's String values are immutable: once a string is created, its characters cannot be changed. Concatenation therefore creates a new String containing the combined text.
For text that includes variables or expressions, Kotlin usually prefers string templates:
val name = "Ada"
val message = "Hello, $name!"
This is concise and readable. Use braces when the expression is more than a simple variable name:
val itemCount = 3
val message = "You have ${itemCount + 1} items."
For a small number of pieces, + and string templates are clear and appropriate. If you are building a large string repeatedly in a loop, use StringBuilder to avoid creating many intermediate strings.
Mental Model
Think of a String as a printed label. You cannot erase or extend the label after it is printed.
When you write:
val fullName = firstName + " " + lastName
Kotlin produces a new label that contains all three pieces.
A string template is like a label printer with blanks to fill in:
"Welcome, $name"
For many repeated additions, StringBuilder is like writing onto a reusable whiteboard and printing the final label only when you are done.
Syntax and Examples
Use + to join strings:
val greeting = "Hello " + "World"
println(greeting) // Hello World
+ can combine a string with other values. Kotlin converts the other value to text:
val score = 42
val message = "Score: " + score
println(message) // Score: 42
Prefer string templates when inserting values into text:
val user = "Mina"
val points = 125
val message = "$user has $points points."
println(message) // Mina has 125 points.
Use ${...} for a property access, function call, or calculation:
val product = "notebook"
val quantity = 2
println("Product: ${product.uppercase()}")
println("Total items: ${quantity * 3}")
For many additions, use StringBuilder:
val builder = StringBuilder()
builder.append("Hello")
builder.append(", ")
builder.append("World")
val greeting = builder.toString()
println(greeting) // Hello, World
Step by Step Execution
Consider this code:
val firstName = "Grace"
val lastName = "Hopper"
val fullName = firstName + " " + lastName
val message = "Welcome, $fullName!"
println(message)
Execution proceeds as follows:
firstNamerefers to the string"Grace".lastNamerefers to the string"Hopper".- Kotlin evaluates
firstName + " ", producing"Grace ". - It joins that result with
lastName, producing a new string:"Grace Hopper". - The template
"Welcome, $fullName!"inserts the value offullName. printlndisplays:
Welcome, Grace Hopper!
Real World Use Cases
String concatenation and templates are useful whenever an application creates human-readable text.
-
User interface labels:
val heading = "Welcome back, $displayName" -
API paths and query values:
val endpoint = "/users/$userId/orders" -
Log messages:
println("Request failed with status $statusCode") -
Validation feedback:
val error = "Password must contain at least $minimumLength characters." -
Reports and exports:
val row = "$customerId,$customerName,$total"
For structured formats such as JSON, use a serializer or JSON library rather than manually joining strings. Manual concatenation can create invalid output when values contain quotes, commas, or special characters.
Real Codebase Usage
In production Kotlin code, developers generally use templates for readable messages and StringBuilder for repeated assembly.
String templates for logs and messages
fun describeOrder(orderId: Long, status: String): String {
return "Order $orderId is $status"
}
Guard clauses with useful error messages
fun requirePositiveQuantity(quantity: Int) {
require(quantity > 0) {
"Quantity must be positive, but was $quantity."
}
}
The message is created only if the condition fails because require accepts a lambda for its message.
buildString for multiline or conditional text
Kotlin provides buildString, which creates and returns a string using a StringBuilder internally:
fun createProfileSummary(name: String, email: String?, isAdmin: Boolean): String = buildString {
appendLine("Name: $name")
if (email != null) {
appendLine("Email: $email")
}
if (isAdmin) {
append("Role: administrator")
}
}
This pattern is useful when parts of the output depend on conditions or are added in a loop.
Repeated output in a loop
val csv = buildString {
for (name in listOf("Ana", "Bo", "Chen")) {
appendLine(name)
}
}
This avoids repeatedly assigning a larger and larger immutable string.
Common Mistakes
Expecting a string to change
Strings are immutable. This does not modify message:
val message = "Hello"
// message += " World" // Error: val cannot be reassigned
Use a new val or a mutable var when reassignment is genuinely needed:
var message = "Hello"
message += " World"
For repeated changes, prefer StringBuilder or buildString.
Forgetting spaces and punctuation
Concatenation does not insert separators automatically:
val broken = "Hello" + "World"
println(broken) // HelloWorld
Add the separator yourself:
val correct = "Hello " + "World"
Using $value for a complex expression
A simple name works after $, but expressions need braces:
val count = 4
// println("Next: $count + 1") // Prints: Next: 4 + 1
println("Next: ${count + 1}") // Prints: Next: 5
Concatenating repeatedly in a large loop
This works but can create many intermediate strings:
var report = ""
for (number in 1..10_000) {
report += "$number\n"
}
Use buildString instead:
val report = buildString {
for (number in 1..10_000) {
appendLine(number)
}
}
Building JSON manually
This is unsafe if name contains quotes or special characters:
val json = "{\"name\": \"$name\"}"
Use a JSON serialization library for JSON data.
Comparisons
| Approach | Best for | Example | Notes |
|---|---|---|---|
+ | Joining a few pieces of text | "Hello " + name | Clear for simple cases. |
| String template | Text containing values | "Hello, $name" | Usually the most readable Kotlin style. |
${...} template | Expressions and calls | "Total: ${price * quantity}" | Braces are required around non-simple expressions. |
StringBuilder | Many incremental additions | builder.append(line) | Efficient when adding text repeatedly. |
buildString | Kotlin-friendly conditional or loop-based construction | buildString { append(name) } | Convenient wrapper around StringBuilder. |
Java's String.concat() joins exactly two strings:
String result = "Hello ".concat("World");
In Kotlin, use + or a template instead:
val result = "Hello " + "World"
val sameResult = "Hello World"
Kotlin can call many Java methods when interoperating with Java code, but + and templates are the idiomatic choices for normal Kotlin string construction.
Cheat Sheet
// Join strings
val text = "Hello " + "World"
// Insert a variable
val message = "Hello, $name"
// Insert an expression, property, or function result
val total = "Total: ${price * quantity}"
val upper = "Name: ${name.uppercase()}"
// Build text in a loop or with conditions
val output = buildString {
appendLine("Header")
append("Footer")
}
Stringis immutable; concatenation creates a new string.- Use
+for a few values. - Prefer templates for messages containing variables.
- Use
${...}for calculations, calls, and anything more than a simple variable name. - Use
StringBuilderorbuildStringfor many repeated additions. - Add spaces, commas, and newlines explicitly; Kotlin does not add them automatically.
FAQ
Is + the correct way to concatenate strings in Kotlin?
Yes. + is the standard choice for joining a small number of strings. String templates are often even more readable when values are embedded in text.
Does Kotlin have String.concat()?
Kotlin code typically uses + rather than concat(). When working with Java APIs, some Java string functionality may be accessible, but it is not the usual Kotlin style.
Should I use + or string templates in Kotlin?
Use + when joining separate pieces. Use templates when writing a sentence, label, log message, or other text containing values.
val path = "/users/" + userId
val message = "User ID: $userId"
When should I use ${} in a Kotlin string template?
Use ${} for expressions, method calls, and calculations.
val label = "Length: ${name.length}"
Is + slow for Kotlin strings?
It is fine for a small number of concatenations. For repeated concatenation in a large loop, use StringBuilder or buildString.
Can I concatenate a string and an integer in Kotlin?
Yes.
val message = "Attempt: " + 3
A template is often cleaner:
val message = "Attempt: $attempt"
Does + add a space between strings?
No. Add spaces or other separators explicitly.
val fullName = "$firstName $lastName"
Mini Project
Description
Create a receipt formatter for a small checkout flow. The formatter combines item information, calculates totals, and conditionally adds a discount line. It demonstrates string templates for normal text and buildString for constructing several lines of output.
Goal
Generate a readable, multiline receipt from a product name, quantity, unit price, and optional discount.
Requirements
- Accept a product name, quantity, unit price, and discount percentage.
- Calculate the subtotal and final total.
- Include the product, quantity, and subtotal in the receipt.
- Include a discount line only when the discount is greater than zero.
- Return the finished receipt as one multiline string.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.