Order of init calls in Kotlin Array initialization

后端 未结 2 1814
轮回少年
轮回少年 2020-12-12 00:23

In the constructor of an Array is there a guarantee that the init function will be called for the indexes in an increasing order?

It would make sense but I did not f

相关标签:
2条回答
  • 2020-12-12 01:07

    Starting from the version 1.3.50 Kotlin has guaranteed sequential array initialization order in its API documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/-init-.html

    The function init is called for each array element sequentially starting from the first one. It should return the value for an array element given its index.

    0 讨论(0)
  • 2020-12-12 01:08

    There is no guarantee for this in the API.

    TLDR: If you need the sequential execution, because you have some state that changes see bottom.

    First lets have a look at the implementations of the initializer:

    Native: It is implemented in increasing order for Kotlin Native.

    @InlineConstructor
    public constructor(size: Int, init: (Int) -> Char): this(size) {
        for (i in 0..size - 1) {
            this[i] = init(i)
        }
    }
    

    JVM: Decompiling the Kotlin byte code for

    class test {
        val intArray = IntArray(100) { it * 2 }
    }
    

    to Java in Android Studio yields:

    public final class test {
       @NotNull
       private final int[] intArray;
    
       @NotNull
       public final int[] getIntArray() {
          return this.intArray;
       }
    
       public test() {
          int size$iv = 100;
          int[] result$iv = new int[size$iv];
          int i$iv = 0;
    
          for(int var4 = result$iv.length; i$iv < var4; ++i$iv) {
             int var6 = false;
             int var11 = i$iv * 2;
             result$iv[i$iv] = var11;
          }
    
          this.intArray = result$iv;
       }
    }
    

    which supports the claim that it is initialized in ascending order.

    Conclusion: It commonly is implemented to be executed in ascending order.

    BUT: You can not rely on the execution order, as the implementation is not guaranteed by the API. It can change and it can be different for different platforms (although both is unlikely).

    Solution: You can initialize the array manually in a loop, then you have control about the execution order. The following example outlines a possible implementation that has a stable initialisation with random values, e.g. for tests.

    val intArray = IntArray(100).also {
        val random = Random(0)
        for (index in it.indices) {
            it[index] = index * random.nextInt()
        }
    }
    
    0 讨论(0)
提交回复
热议问题