38

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
    }
}
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • There are newer answers that are current for Kotlin. – Jayson Minard Dec 28 '15 at 16:47
  • 1
    This question is now answered by the more current and complete: http://stackoverflow.com/questions/34498562 After that question has accepted answer and votes, this should be closed as duplicate of that. In meta.stackexchange.com one recommended way to modernize questions and answers is to create a new one, and then close the old while adding a reference to the new. – Jayson Minard Dec 28 '15 at 18:14

7 Answers7

38

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

Community
  • 1
  • 1
Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
11

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/

egaga
  • 21,042
  • 10
  • 46
  • 60
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • By the way, this example shows that even if map.contains(n) is true, in multithreaded environment, map.get(n) can result in null value. – Nikita Skvortsov Aug 19 '13 at 20:05
  • 2
    Why not change the answer to be current and drop the `.sure()` answer entirely since it is completely wrong for current Kotlin. – Jayson Minard Dec 28 '15 at 16:34
9

You can also use a default value in null case:

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

VKostenc
  • 1,140
  • 14
  • 19
4

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

rsanath
  • 1,154
  • 2
  • 15
  • 24
4

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.

Franck Rasolo
  • 539
  • 4
  • 9
  • How can I use a map of `Int` then? I am always inserting non-nullable ints into the map, so they are guaranteed to be not-null. – jjnguy Mar 05 '12 at 14:01
  • Also, I'd love to contribute to the Euler project and perhaps augmenting some flog the std libs. – jjnguy Mar 05 '12 at 14:01
  • As you've probably figured out, the downside of relying on `sure()` is that you lose null safety at runtime. However, since you are certain that you are always mapping keys to non _null_ values, you should go ahead and use `sure()` regardless. – Franck Rasolo Mar 05 '12 at 20:35
  • As for helping solve Project Euler (PE) problems, my understanding is that the PE site administrators strongly discourage collaboration and rather encourage people to individually explore the mathematical concepts behind each problem. – Franck Rasolo Mar 05 '12 at 20:40
  • I'm not interested in the mathematical implications of the problems, (I've solved lost of them before) I'm interested in creating a good reference for the language as well as contribute to its development. – jjnguy Mar 05 '12 at 20:51
  • Please replace sure with `!!` in your answer, since it is not part of Kotlin for years. – Jayson Minard Dec 28 '15 at 16:35
3

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) }
}
Sergey Mashkov
  • 4,630
  • 1
  • 27
  • 24
3

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
Alf Moh
  • 7,159
  • 5
  • 41
  • 50