Порядок инициализации вызовов в инициализации Kotlin Array - PullRequest
3 голосов
/ 11 мая 2019

В конструкторе массива есть гарантия, что функция init будет вызываться для индексов в возрастающем порядке?

Это имело бы смысл, но я не нашел такой информации в документации:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/-init-.html#kotlin.Array%24%28kotlin.Int%2C+kotlin.Function1%28%28kotlin.Int%2C+kotlin.Array.T%29%29%29%2Finit

1 Ответ

6 голосов
/ 12 мая 2019

На это нет никаких гарантий в API.

TLDR: Если вам нужно последовательное выполнение, потому что у вас есть какое-то состояние, которое изменяется, см. Bottom.

Сначала давайте взглянем на реализации инициализатора:

Собственный: Он реализован в возрастающем порядке для Собственный Kotlin .

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

JVM : декомпилирование байт-кода Kotlin для

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

для Java в Android Studio дает:

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;
   }
}

, что подтверждает утверждение, что оно инициализируется в порядке возрастания.

Вывод: Обычно он реализуется в порядке возрастания.

НО: Нельзя полагаться на порядок выполнения, так как реализация не гарантируется API.Это может измениться, и это может быть различным для разных платформ (хотя обе маловероятны).

Решение: Вы можете инициализировать массив вручную в цикле, тогда у вас есть контроль над порядком выполнения,В следующем примере описывается возможная реализация, которая имеет стабильную инициализацию со случайными значениями, например, для тестов.

val intArray = IntArray(100).also {
    val random = Random(0)
    for (index in it.indices) {
        it[index] = index * random.nextInt()
    }
}
...