I want a class which is equivalent to Java Optional but also
Non-working code:
class MutableOptional<T> {
private var value: T? = null
private var isSet: Boolean = false
fun set(value: T)
{
this.value = value
isSet = true
}
fun unset()
{
isSet = false
value = null
}
fun get(): T
{
if (!isSet) {
throw Error("Value not set")
}
return value!! // <<< NPE here
}
}
fun f()
{
val opt = MutableOptional<Int?>()
opt.set(null)
assertNull(opt.get())
}
The problem is that if I try to set null, get() call fails with null pointer exception (caused by !! operator).
Some not-working proposals:
Note: This example is synthetic, I do not really need the mutable optional, it is just a simple and understandable example, illustrating a problem I encounter occasionally with Kotlin generics and null-safety. Finding solution to this particular example will help with many similar problems. Actually I have a solution for immutable version of this class but it involves making interface and two implementation classes for present and non-present values. Such immutable optional can be used as type of "value" member but I think it's quite big overhead (accounting also wrapper object creation for each set()) just to overcome the language constraints.
When mapping an Optional in Java, sometimes you have to unwrap another Optional . To do this, you use flatMap() instead of map() . With Kotlin's null system, the value is either present, or null , so there's nothing to unwrap. This means that Kotlin's equivalent for flatMap() and map() are similar.
Nullability and Nullable Types in Kotlin That means You have the ability to declare whether a variable can hold a null value or not. By supporting nullability in the type system, the compiler can detect possible NullPointerException errors at compile time and reduce the possibility of having them thrown at runtime.
Mutability is a core concept in Kotlin, but all is perhaps not what it seems. The fundamental concept here is if we declare variables using var then they are mutable and can be reassigned with another value, whereas if we declare variables using val then they are immutable and cannot be reassigned.
Kotlin has a safe call operator (?.) to handle null references. This operator executes any action only when the reference has a non-null value. Otherwise, it returns a null value. The safe call operator combines a null check along with a method call in a single expression.
The compiler wants you to write code that will be type-safe for all possible T
, both nullable and not-null (unless you specify a not-null upper bound for the type parameter, such as T : Any
, but this is not what you need here).
If you store T?
in a property, it is a different type from T
in case of not-null type arguments, so you are not allowed to use T
and T?
interchangeably.
However, making an unchecked cast allows you to bypass the restriction and return the T?
value as T
. Unlike the not-null assertion (!!
), the cast is not checked at runtime, and it won't fail when it encounters a null
.
Change the get()
function as follows:
fun get(): T {
if (!isSet) {
throw Error("Value not set")
}
@Suppress("unchecked_cast")
return value as T
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With