Kotlin boxed Int are not the same

2019-01-28 06:55发布

问题:

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.

回答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.



回答2:

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


回答3:

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.