Question

I'm using a HashMap<Int, Int> in Kotlin and when I get out of it the return type is Int?.

How can I convert the Int? to an Int?

So far I've tried using Int?.toInt(), but that seems to be returning an Int?.

I'm writing a Fibonacci function, and my code looks like:

val fibMemo : Map<Int, Int> = HashMap<Int,Int>()
fun fibN(n:Int) : Int {
    if (n == 0 || n == 1) return 1
    if (fibMemo.containsKey(n))
        // Error here: Type mismatch: inferred type is Int? but Int was expected
        return fibMemo.get(n)?.toInt()
    else {
        val newNum : Int = fibN(n-1) + fibN(n-2)
        fibMemo.put(n, newNum)
        return newNum
    }
}
Was it helpful?

Solution

The direct answer, use the !! operator to assert that you trust a value is NOT null and therefore changing its type to the non null equivalent. A simple sample showing the assertion allowing the conversion (which applies to any nullable type, not just Int?)

val nullableInt: Int? = 1
val nonNullableInt: Int = nullableInt!! // asserting and smart cast

Another way to convert a value is via a null check. Not useful in your code above, but in other code (see Checking for null in conditions):

val nullableInt: Int? = 1
if (nullableInt != null) {
   // allowed if nullableInt could not have changed since the null check
   val nonNullableInt: Int = nullableInt
}

This questions is also answered by the idiomatic treatment of nullability question: In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them

OTHER TIPS

In order to convert an Int? to an Int use the sure() method.

The offending line should look like:

return fibMemo.get(n).sure()

Call to method sure() is Kotlin way (soon to be replaced by special language construct) to ensure non-nullability. As Java has not notation of nullable and non-nullable types we need to take some care on integration point. Please read amazing story of null-safety in Kotlin documentation.

source

Warning: the above information doesn't hold anymore. sure has been replaced by !!. See: http://blog.jetbrains.com/kotlin/migrating-sure/

The easiest way is to use a null check

var a : Int? = 12
var b : Int      
b = a // error!
b = if(a != null) a else -1    //automatic typecast from Int? to Int

You can refer more about null-safe Type casts over here : Null Safety - Kotlin

You can also use a default value in null case:

val int: Int val nullableInt: Int? = null int = nullableInt ?: 0

You also can use getOrPut function to avoid contains/put in you code. See

val fibMemo = HashMap<Int, Int>()
fun fibN(n: Int): Int = when {
    n < 0 -> throw IllegalArgumentException("fib is not applicable to $n")
    n == 0, n == 1 -> 1
    else -> fibMemo.getOrPut(n) { fibN(n - 1) + fibN(n - 2) }
}

In addition to checking for the presence of the key, you will also need to ensure that the returned value is not null as java.util.HashMap allows null values.

You can do that by either surrounding your call to get with an explicit null check or by invoking !! on the returned value.

Your workaround to use as Int will be flagged as an unsafe cast warning by IDEA, and therefore is not advisable.

The short answer is you can't unless you emphatically state to the compiler that the nullable int can't and won't be null through the use of two exclamation marks or through the use of an if statement; because int is a subtype of int?

Here is an example.

val x:Int? = 1
val y: Int =2

x=y // No error
y=x // Error
y=x!! // No error
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top