Рубрики
Без рубрики

Массивы примитивов и объектов Котлина

Я изначально намеревался написать этот пост, потому что я играл с некоторым кодом отражения и… С тегами kotlin, java, начинающие.

Изначально я намеревался написать этот пост, потому что я играл с некоторым кодом отражения и подумал, что нашел что-то интересное. Увы, это было определенно не так. Вместо этого это была просто базовая функция Kotlin, которую мне пока не нужно было использовать или на которой я еще не фокусировался. Хотя этот пост получился не таким, каким я хотел его видеть, я все же думаю, что это хороший небольшой пост, чтобы внести некоторую ясность в эту тему.

В Java существует понятие примитивных типов и их завернутые версии . Благодаря автоматической упаковке и распаковке типы могут быть заменены между их примитивными и обернутыми версиями. Другими словами, в большинстве ситуаций вы можете использовать длинный вместо Длинный или Длинный вместо/|длинный . Если вы не заметили, где были прописные буквы в этом последнем предложении, то я полагаю, что это, вероятно, выглядело довольно запутанно. Формулировка в этом предложении также имеет решающее значение. Более конкретно, утверждение "в большинстве ситуаций".

Автоматическая упаковка и распаковка не работают при попытке обмена примитивным массивом и обернутым массивом ( Объект ). Например,

public class PrimitiveArrays {

  public static void main(String args[]) {
    Long[] longArray = new Long[] {1L, 2L, 3L};
    takesInPrimitiveLongArray(longArray);
  }

  static void takesInPrimitiveLongArray(long[] array) {}
}

Это не работает, и попытка его компиляции приводит к следующей ошибке:

error: incompatible types: Long[] cannot be converted to long[]
    takesInPrimitiveLongArray(longArray);

Переключение метода на/|Длинный[] и передача длинного [] также не удастся скомпилировать по тем же причинам. Это не то, что большинству разработчиков Java покажется интересным, но помогает заложить основу для фактического содержания этого поста.

Kotlin должен предоставить вам эквивалент примитивных массивов Java. Но Kotlin не позволяет определять массивы, используя тот же синтаксис, что и Java. В Котлине инициализация массива выглядит так:

val array = Array(3)
// or
val array: Array = arrayOf(1,2,3)

Тот факт, что вы можете видеть, что Массив использует универсальные типы, должен подчеркнуть, что это не примитивный массив. Это факт как в Java, так и в Kotlin, что универсальные типы не могут быть примитивами. В противном случае его можно было бы заменить на Массив<длинный> , и мы все были бы счастливы. Приведенный выше код компилируется в массив объектов Long[] вместо примитива long [] .

Эта ситуация в некоторой степени уникальна для массивов. Котлин Длинный , используемый сам по себе, может компилироваться в любой Длинный или длинный в байт-коде JVM. Скомпилированный тип зависит от возможности обнуления поля. Массивы являются более явными, поэтому их типы не изменяются при компиляции.

Чтобы обойти это, Kotlin предоставляет набор классов, которые становятся примитивными массивами при компиляции в байт-код JVM.

Эти классы включают:

байт[] Байтрейр
символ[] Хараррей
короткий [] Короткий путь
инт[] ИнтАррей
длинный [] Длинный путь
двойной[] Двойное изображение
поплавок[] Поплавковая решетка
логический[] Логический массив

Существуют также дополнительные классы для массивов беззнаковых типов.

Эти классы также могут быть заменены между Kotlin и Java без каких-либо дополнительных усилий.

В качестве последнего доказательства, показывающего вам различия между примитивными и обернутыми/объектными массивами в Kotlin, я хочу показать вам некоторый код Kotlin, который преобразуется в его аналог Java:

@file:JvmName("PrimitiveArrays")
package dev.lankydan

fun main(args: Array) {
  // long and Long arrays
  val longArray = longArrayOf(1,2,3,4)
  val arrayOfLongs = arrayOf(1,2,3,4)
  // int and Integer arrays
  val intArray = intArrayOf(1,2,3,4)
  val arrayOfInts = arrayOf(1,2,3,4)
  // boolean and Boolean arrays
  val booleanArray = booleanArrayOf(true, false)
  val arrayOfBooleans = arrayOf(true, false)
  // char and Character arrays
  val charArray = charArrayOf('a','b','c')
  val arrayOfChars = arrayOf('a', 'b', 'c')
}

Используя декомпилятор байт-кода Kotlin от Intellij, фрагмент кода декомпилируется в:

public final class PrimitiveArrays {
   public static final void main(String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      // long and Long arrays
      long[] var10000 = new long[]{1L, 2L, 3L, 4L};
      Long[] var9 = new Long[]{1L, 2L, 3L, 4L};
      // int and Integer arrays
      int[] var10 = new int[]{1, 2, 3, 4};
      Integer[] var11 = new Integer[]{1, 2, 3, 4};
      // boolean and Boolean arrays
      boolean[] var12 = new boolean[]{true, false};
      Boolean[] var13 = new Boolean[]{true, false};
      // char and Character arrays
      char[] var14 = new char[]{'a', 'b', 'c'};
      Character[] var15 = new Character[]{'a', 'b', 'c'};
   }
}

Во-первых, обратите внимание, что Kotlin предоставляет вам полезные функции инициализации для ваших массивов. Как для примитивных, так и для объектных массивов. Во-вторых, как они составляются. Например, Длинный массив становится длинным[] и Массив<Длинный> становится Длинным[] .

Теперь вы можете видеть различия между этими массивами. Но я не упомянул, какие из них вы должны использовать. Вы должны полагаться на примитивные типы так же, как это делает Java. Это связано с влиянием на производительность, которое может оказать автоматическая упаковка и распаковка на ваше приложение.

Для небольших рабочих нагрузок результат, скорее всего, будет незначительным. С другой стороны, для больших массивов в критически важных для производительности приложениях это, возможно, небольшое изменение может оказать заметное влияние. Дополнительную информацию по этому вопросу можно найти здесь .

Если вам нужно хранить нули в своих массивах, вам все равно нужно будет вернуться к массиву обернутых/объектов. В большинстве ситуаций, я думаю, вы должны иметь возможность использовать примитивные массивы, но всегда будут моменты, когда вы не сможете. Тем не менее, большую часть времени мы все просто используем Список s, так что все это на самом деле не имеет значения 😛 .

Теперь вы должны лучше понимать различия между примитивными массивами, такими как Длинный массив и массивы объектов, такие как Массив<Длинный> . Если нет, то я подвел вас, и я приношу извинения за это”.

Если вы сочли этот пост полезным, вы можете подписаться на меня в Твиттере по адресу @Lankydandev , чтобы быть в курсе моих новых постов.

Оригинал: “https://dev.to/lankydandev/kotlin-primitive-and-object-arrays-4dp0”