1. Introduction

In Kotlin, mapping java.util.Optional to T is a common task that developers encounter when working with Java libraries. Kotlin provides convenient methods to achieve this mapping, making the process more streamlined and concise.

In this tutorial, we’ll explore three methods in Kotlin for mapping java.util.Optional to its underlying value: getOrNull(), getOrElse(), and getOrDefault(). These methods allow for easy retrieval and transformation of optional values, enhancing the development experience in Kotlin.

2. Using getOrNull()

The getOrNull() method allows us to retrieve the value of an Optional object if it is present, or return null if it is empty. This method is useful when we want to map the Optional to a nullable type in Kotlin:

val optionalValue: Optional<String> = Optional.of("Hello, Baeldung!")
val value: String? = optionalValue.getOrNull()

In the above code snippet, getOrNull() is called on the optionalValue object, which returns the underlying value “Hello, Baeldung!” as a nullable String. If the Optional object is empty, getOrNull() will return null.

3. Using getOrElse() and getOrDefault()

The getOrDefault() and getOrElse() methods serve similar purposes of retrieving a value from an Optional when it is present. However, there’s a key difference between the two methods:

  • getOrDefault() allows us to specify a default value that will be returned directly if the Optional is empty.
  • getOrElse() allows us to specify a lambda expression that will be evaluated, and its result will be returned as the default value if the Optional is empty. This provides flexibility in generating the default value dynamically.

Let’s see some quick examples:

val optionalValue: Optional<String> = Optional.empty()

val value1: String = optionalValue.getOrDefault("Default Value")

val value2: String = optionalValue.getOrElse { "Default Value" }

By understanding the distinction between getOrDefault() and getOrElse(), we can choose the method that best fits the requirements.

If we need a fixed default value, getOrDefault() is suitable. On the other hand, if we want to generate the default value dynamically, based on certain conditions or calculations, getOrElse() provides the flexibility to do so. One common use for this flexibility is to throw an exception from within getOrElse() to represent an unexpected state on our optional:

val value: String = optionalValue.getOrElse { throw IllegalStateException("Value is missing") }

4. Kotlin’s Nullability vs. Java’s Optional

In Kotlin, the concept of nullability is seamlessly integrated into the language itself, providing a more streamlined approach to handling nullable values compared to Java’s Optional interface. The Optional interface in Java serves the purpose of providing a null-safe approach to transforming values. However, in Kotlin, the null safety features make the Optional interface unnecessary.

Kotlin’s type system distinguishes between nullable and non-nullable types, enabling built-in null safety checks and providing concise syntax for handling nullable values. This eliminates the need for additional interfaces like Optional and their associated methods.

By leveraging Kotlin’s nullability features, developers can write cleaner and more expressive code while ensuring null safety throughout their applications. The elimination of the Optional interface aligns with Kotlin’s philosophy of reducing boilerplate and enhancing developer productivity. Let’s take a look at a sample from both languages to illustrate this:

public String getUsername(User user) {
    Optional<User> optionalUser = Optional.ofNullable(user);
    return optionalUser.map(User::getName).orElse("Unknown");
}
fun getUsername(user: User?): String {
    return user?.name ?: "Unknown"
}

5. Conclusion

In this article, we explored three convenient methods in Kotlin to map an Optional object to its underlying value: getOrNull(), getOrElse(), and getOrDefault(). These methods provide flexibility in handling nullable and non-null types, as well as the ability to define default values.

By utilizing these methods, we can write cleaner and more concise code when working with Optional objects in Kotlin. Moreover, we emphasized the Kotlin-esque approach to handling optional values, which leverages the language’s null safety features and type system. As usual, the code used in this article is available over on GitHub.