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.

holi-java
  • 29,655
  • 7
  • 72
  • 83
kotlinhelp
  • 167
  • 1
  • 6
  • 3
    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) – danielspaniol Jul 17 '17 at 08:34
  • 4
    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. – Alf Moh Jul 17 '17 at 09:03
  • @danielspaniol maybe I'll let you disappointed [here](https://stackoverflow.com/a/45144516/7607923), :) – holi-java Jul 21 '17 at 22:01
  • @holi-java why disappointed. It also states that `Int` maps to `int` and `Int?` to `Integer`. Or do you mean because of the caching range? – danielspaniol Jul 24 '17 at 16:17
  • @danielspaniol because they are maybe don't the same. – holi-java Jul 24 '17 at 16:18

3 Answers3

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
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
holi-java
  • 29,655
  • 7
  • 72
  • 83
  • " 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? – NullByte08 May 15 '20 at 12:46
  • @NullByte08 Hi, due to java does not allow primitive types for generic [parameterized types](https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.5), 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. – holi-java May 15 '20 at 14:40
  • But then why is `val list:List = 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 :) – NullByte08 May 17 '20 at 08:20
  • @NullByte08 Hi, I have mentioned that since the [nullable/non-nullable](https://kotlinlang.org/docs/reference/comparison-to-java.html#what-kotlin-has-that-java-does-not) 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](https://kotlinlang.org/docs/reference/null-safety.html). – holi-java May 17 '20 at 13:44
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.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
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.

zsmb13
  • 85,752
  • 11
  • 221
  • 226