Why do I get `false` in code below `fun main() {` ...
# getting-started
t
Why do I get
false
in code below
fun main() {
val a: Int = 1000
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA === anotherBoxedA) // false
}
?
e
the same structural `equals`/`==
value can be represented by many different instances, and
===` compares whether two references are the same instance
1
this can be easily seen in non-primitive types, for example
Copy code
String() == String()
String() !== String()
for
Int
, it is represented as a primitive where possible, but the compiler will auto-box it (using valueOf) when needed
if we create new boxed instances ourselves, we can easily see that they are different:
Copy code
Integer(0) == Integer(0)
Integer(0) !== Integer(0)
so really the question is, why does
Copy code
Integer.valueOf(0) === Integer.valueOf(0)
while
Copy code
Integer.valueOf(1000) !== Integer.valueOf(1000)
and that is because of the small integer cache
when reading the article, keep in mind that for reference types, Kotlin's
==
is Java's
.equals()
and Kotlin's
===
is Java's
==
, but Kotlin generally has the same operational semantics as Java for the same structures (as it most commonly runs on JVM, and even Kotlin Multiplatform usually has similar behavior)
s
Wait, so, is there some kind of copying happening here behind the scenes? because to me it looks like they're assigning the same (reference to a) boxed int to two different variables which should then have the same identity (and should therefore pass a
===
check)
e
no.
a
is not a reference, but
boxedA
and
anotherBoxedA
are, so it gets compiled into
Copy code
Integer boxedA = Integer.valueOf(a);
Integer anotherBoxedA = Integer.valueOf(a);
s
oh, okay, so not copying per se, but definitely some new object construction
I remember reading something a while back saying that all `Int`s were, effectively,
Integer
instances (and then therefore would be references), but I suppose there must be optimizations around primitive type usage on the JVM that allow this to happen
e
you are mistaken
primitives have a distinct representation with no instances. there are (non-unique) reference wrappers for all primitive types. Java auto-boxing and -unboxing largely hides the difference, and Kotlin hides it even more