1

I am a beginner of kotlin.

I do not understand the output below.

@Test
fun testNumberBoxing() {

    val a:Int = 1000
    val boxedA1: Int? = a
    val boxedA2: Int? = a

    println("first check = ${boxedA1 === boxedA2}")

    val b: Int = 2
    val boxedB1: Int? = b
    val boxedB2: Int? = b

    println("second check = ${boxedB1 === boxedB2}")
}

result is

first check = true
second check = false

Why are the two outputs different?

my kotlin version is 1.2.31

org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.31
ohlab
  • 467
  • 5
  • 7

3 Answers3

3

The output I got

first check = false
second check = true

What the code compiles to

public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      int a = 1000;
      Integer boxedA1 = Integer.valueOf(a);
      Integer boxedA2 = Integer.valueOf(a);
      String var4 = "first check = " + (boxedA1 == boxedA2);
      System.out.println(var4);
      int b = 2;
      Integer boxedB1 = Integer.valueOf(b);
      Integer boxedB2 = Integer.valueOf(b);
      String var7 = "second check = " + (boxedB1 == boxedB2);
      System.out.println(var7);
}

Why valueOf is not consistent

For this we need to look at the JavaDoc of valueOf:

Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

As you can see, for small values it will return the same object on both calls, so they are equal, and for the larger uncached value the 2 objects are different

In java the == checks for object equality, so the 2 equal objects are false, while 2 copies of the same object returns true.

jrtapsell
  • 6,719
  • 1
  • 26
  • 49
2

That's rather weird, I'm consistently (both locally and on try.kotlinlang.org with different Kotlin versions) getting this result instead:

first check = false
second check = true

And this is what is to be expected, as the JVM caches Integer instances int the -127 to 128 range, reusing the same Integer instance when one is required for boxing, literals, or Integer.valueOf calls in this range.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
0

In contrast to php or javascript where === is in most cases the more sane option, in Kotlin === compares references to objects instead of values.

As others pointed out, objects for Integers of the same value can be cached. Same goes for Strings and the other primitive types.

Saskia
  • 1,046
  • 1
  • 7
  • 23