Back to Dev Logs

Dev Logs / 4 min read

Kotlin 2.4.0: New Features That Confuse Patrick (Again)

Kotlin 2.4.0: New Features That Confuse Patrick (Again)
Kotlin 2.4.0: New Features That Confuse Patrick (Again)

Patrick: "SpongeBob, they say there's a new Kotlin out, version 2.4.0. Does it taste good?"

SpongeBob: "Patrick... this isn't ice cream. It's a programming language release. But don't worry, I'll walk you through it with some code examples."

Patrick: "Okay, just don't use hard words like 'covariance' again."

SpongeBob: "Can't promise that. But this time we'll cover the parts that are the most exciting and the most useful for everyday work."


Kotlin 2.4.0: New Features That Confuse Patrick (Again)
Kotlin 2.4.0: New Features That Confuse Patrick (Again)

1. Collection Literals — Building Lists Like Regular Arrays

Up until now, creating a List or MutableList in Kotlin meant writing listOf(...) or mutableListOf(...). Now, Kotlin 2.4.0 introduces collection literals — a way to build collections using square brackets [], similar to Python or JavaScript.

Patrick: "So it's like making a jellyfish shopping list?"

SpongeBob: "Exactly! Look at this:"

fun main() {
    // Old way
    // val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")

// New way with a collection literal
val shapes: MutableList<String> = ["triangle", "square", "circle"]
println(shapes)
// [triangle, square, circle]
}
```

If the compiler can't infer the collection type, it defaults to List:

fun main() {
    val fruit = ["apple", "banana", "cherry"]
    println(fruit)
    // [apple, banana, cherry]
}

Even better, you can define your own operator fun of so your custom types can also use bracket syntax — great if you're working with structures like matrices or grids.

Note: this feature is still Experimental, so it has to be enabled manually in build.gradle.kts:

kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xcollection-literals")
    }
}

Patrick: "Wow, that's so easy — why didn't they do this from the start?"

SpongeBob: "Because there's a lot to think through, Patrick. Including backward compatibility."


<!-- UPLOAD IMAGE HERE: 03-context-parameters.png (drag & drop directly into the Medium editor at this spot) -->

2. Context Parameters — Officially Stable!

This is the one everyone's been waiting for. Context parameters, experimental since Kotlin 2.2.0, are now Stable in 2.4.0. This feature lets us declare the implicit dependencies a function needs, without passing them explicitly on every call.

Patrick: "Implicit is like... a ninja? Unseen but there?"

SpongeBob: "You could say that. Here's an example:"

class EmailSender
class SmsSender

context(emailSender: EmailSender)
fun sendNotification() {
println("Sent email notification")
}

context(smsSender: SmsSender)
fun sendNotification() {
println("Sent SMS notification")
}
```

What's new in 2.4.0 is that we can now pass an explicit context argument when two overloads become ambiguous, without wrapping the call in a context() function:

context(defaultEmailSender: EmailSender, defaultSmsSender: SmsSender)
fun notifyUser() {
    // Selects the overload with the EmailSender context parameter
    sendNotification(emailSender = defaultEmailSender)

// Selects the overload with the SmsSender context parameter
sendNotification(smsSender = defaultSmsSender)
}
```

This explicit context argument feature is still experimental, so it needs its own opt-in (-Xexplicit-context-arguments) in addition to the context parameters flag, which is already stable.

Patrick: "So if there are two twin functions, Kotlin can get confused picking which one to use?"

SpongeBob: "Right, and this feature is what helps Kotlin pick the correct one."


<!-- UPLOAD IMAGE HERE: 04-issorted.png (drag & drop directly into the Medium editor at this spot) -->

3. Checking Sort Order Without Re-sorting: .isSorted()

A small feature, but a genuinely useful one. There's now a new set of extension functions to check whether a collection is already sorted, without sorting it again or writing your own helper function:

  • .isSorted()
  • .isSortedDescending()
  • .isSortedWith(comparator)
  • .isSortedBy(selector)
  • .isSortedByDescending(selector)
data class User(val name: String, val age: Int)

fun main() {
val numbers = listOf(1, 2, 3, 4)
println(numbers.isSorted())
// true

val users = listOf(
User("Alice", 24),
User("Bob", 31),
User("Charlie", 29),
)
println(users.isSortedBy(User::age))
// false
}
```

These functions are also efficient, since they stop as soon as they hit an out-of-order pair — handy for large datasets.

Patrick: "So Kotlin can now say 'yep, this is already tidy' without cleaning it up again?"

SpongeBob: "Exactly, Patrick. Pretty efficient, right?"


4. UUID Finally Goes Stable

Since Kotlin 2.0.20, we've had kotlin.uuid.Uuid in the common standard library. Over several releases it picked up features like < / > comparisons, parsing from hex-and-dash formats, and returning null for invalid UUIDs — and now in Kotlin 2.4.0, the API is officially Stable. The only exception is the functions for generating V4 and V7 UUIDs, which remain experimental.

For Android or KMP projects that frequently need unique identifiers — device IDs, session IDs, or database entity IDs — this is good news, since you no longer need to opt in to use the API.


Closing: A Bug in Bikini Bottom

Patrick: "SpongeBob, I just tried compiling, but it says there's an unrecognized function."

SpongeBob: "Let's check first, Patrick — have you updated the Kotlin plugin to 2.4.0 in your IDE? And if the feature you're using is still experimental, don't forget to add the compiler flag in build.gradle.kts too."

Patrick: "Oh right, I forgot to add the flag!"

SpongeBob: "There you go. Kotlin keeps getting more advanced, but we still have to read the changelog carefully before updating a production build."

Beyond these four highlights, Kotlin 2.4.0 also brings a bunch of other updates: Java 26 support on the JVM, improvements to Kotlin/Native (Swift export promoted to Alpha, CMS garbage collector enabled by default), and refinements across Kotlin/Wasm and Kotlin/JS. If you're curious about the full details, check out the official documentation at kotlinlang.org.

See you in the next Kotlin exploration!