Kotlin boxed Int are not the same
Asked Answered
D

3

13

Please help me understand this piece of code in the kotlin docs:-

val a: Int = 10000
print(a === a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!Prints 'false'!!!

Now, I understand that first int a = 10000 then in the next line it is comparing it using ===.

Now the question is why when it assigned boxedA=a, it checked if it is null using int?. Can it just be written like this:-

val boxedA: Int=a

Please if I'm understanding it the wrong way, someone guide to check the right place or explain it a bit for me.

Distiller answered 17/7, 2017 at 8:30 Comment(5)
while I am not 100% sure I think Int is the same as Javas int (a primitive) while Int? is the same as Integer (an object)Muimuir
Why the down votes? The user clearly stated that, if he/she is understanding it the wrong way, he/she should be guided. I clearly don't see the reason for which this question should be down voted.Grus
@Muimuir maybe I'll let you disappointed here, :)Inventor
@Inventor why disappointed. It also states that Int maps to int and Int? to Integer. Or do you mean because of the caching range?Muimuir
@Muimuir because they are maybe don't the same.Inventor
M
1

when it assigned boxedA = a, it checked if it is null using int?

I have no idea what you mean by this. Making a variable have the type Int? makes it a variable that can either store an Int or null. There is no checking happening at this assignment. If you have a non-null value to assign to the variable, just make it non-nullable, without the ? in the type:

val copyOfA: Int = a

You can even omit the type, and get Int inferred:

val copyOfA = a

As for the comparisons:

== is used for comparing by value in Kotlin (this is the equivalent of using equals in Java), === is used for comparing references (this is == in Java).

When you create boxedA and anotherBoxedA, you create two Integer instances under the hood (because nullable variables can't be represented by primitives). These will be equal when compared with == (they have the same value), but not when compared with === (they are different instances).

You can see the relevant part of the offical docs here.

Mallette answered 17/7, 2017 at 8:46 Comment(0)
I
21

First, the Int will be mapped to java int/Integer depending on its context. If Int is a generic argument, then its mapped type is Integer. Otherwise, it is a primitive type int. for example:

val a:Int = 1 
//final int a = 1; //mapped to java code

val numbers:List<Int> = asList(1,2,3)
//final List<Integer> numbers  = asList(1, 2, 3); //mapped to java code

Secondly, boxing an Int to an Int? is same behavior as java boxing an int to an Integer, for example:

val a:Int = 1   // int a = 1;
val b:Int? = a; // Integer b = a;

Why the boxed Integers are not the same?

This is because Integer only caching values in the range [-128, 127]. the the variable a above is out of the cache range, it will create a new Integer instance for each boxing rather than using a cached value. for example:

//                v--- 1 is in cache range 
val ranged: Int = 1
val boxedRanged1: Int? = ranged
val boxedRanged2: Int? = ranged

println(boxedRanged1 === boxedRanged2) //true

//                   v--- 128 is out of cache range
val excluded: Int = 128
val boxedExcluded1: Int? = excluded
val boxedExcluded2: Int? = excluded

println(boxedExcluded1 === boxedExcluded2) //false
Inventor answered 17/7, 2017 at 12:37 Comment(4)
" If Int is a generic argument, then its mapped type is Integer.". I dont think so, Integer is nullable in java, and Int in Kotlin is not nullable. If you want a generic argument to be nullable in kotlin, it should be declared as Int?Jenine
@Jenine Hi, due to java does not allow primitive types for generic parameterized types, so the actual type arguments Int is mapped to java.lang.Integer by kotlin. and nullable/non-nullable is the enhanced concept in kotlin rather than java.Inventor
But then why is val list:List<Int> = listOf(1,2,null) not valid? Int is mapped to Integer in Java, so null values should be allowed. Can you please explain what do you mean by the "enhanced concept" or maybe point to a source? Thanks :)Jenine
@Jenine Hi, I have mentioned that since the nullable/non-nullable is the kotlin features, so you can also declare the Integer/Integer? if you'd like. on the other hard, from the point of JVM that every reference type can be nullable, but enforced in kotlin by null-safety.Inventor
S
1

it checked if it is null using int?

That is not what it means.

Kotlin's null safety feature does not allow a variable to be set as null by default.

Check here.

val anotherBoxedA: Int? = a

This means that anotherBoxedA can be assigned null or is nullable.

val anotherBoxedA: Int? = null

This will be allowed.

Splenomegaly answered 17/7, 2017 at 8:41 Comment(0)
M
1

when it assigned boxedA = a, it checked if it is null using int?

I have no idea what you mean by this. Making a variable have the type Int? makes it a variable that can either store an Int or null. There is no checking happening at this assignment. If you have a non-null value to assign to the variable, just make it non-nullable, without the ? in the type:

val copyOfA: Int = a

You can even omit the type, and get Int inferred:

val copyOfA = a

As for the comparisons:

== is used for comparing by value in Kotlin (this is the equivalent of using equals in Java), === is used for comparing references (this is == in Java).

When you create boxedA and anotherBoxedA, you create two Integer instances under the hood (because nullable variables can't be represented by primitives). These will be equal when compared with == (they have the same value), but not when compared with === (they are different instances).

You can see the relevant part of the offical docs here.

Mallette answered 17/7, 2017 at 8:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.