IntArray проти Array <Int> у Котліні


88

Я не впевнений, у чому різниця між an IntArrayі an Array<Int>у Kotlin і чому я не можу використовувати їх як взаємозамінні:

невідповідність

Я знаю, що IntArrayперекладається на int[]при націлюванні на JVM, але що означає Array<Int>перекласти?

Крім того, ви також можете мати String[]або YourObject[]. Чому Котлін має класи типу, {primitive}Arrayколи в масив можна впорядкувати майже все, а не лише примітиви.


1
Я припускаю , що Array<Int>компілюється до Integer[](якщо компілятор не оптимізує це)
Mibac


Так, це має великий сенс, дякую вам обом!
FRR

Відповіді:


107

Array<Int>є Integer[]під капотом, тоді як IntArrayє int[]. Це воно.

Це означає, що коли ви ставите Intін Array<Int>, він завжди буде в коробці (зокрема, із Integer.valueOf()дзвінком). У випадку IntArray, бокс не відбудеться, оскільки він перетворюється на примітивний масив Java.


Окрім можливих наслідків для продуктивності вищезазначеного, є також зручність для розгляду. Примітивні масиви можна не ініціалізувати, і вони матимуть 0значення за замовчуванням для всіх індексів. Ось чому, IntArrayа решта примітивних масивів мають конструктори, які приймають лише параметр size:

val arr = IntArray(10)
println(arr.joinToString()) // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

На відміну від цього, Array<T>не має конструктора, який приймає лише параметр розміру: йому потрібні дійсні, не нульові Tекземпляри всіх індексів, щоб бути в дійсному стані після створення. Для Numberтипів це може бути за замовчуванням 0, але немає можливості створити екземпляри за замовчуванням довільного типу T.

Отже, при створенні Array<Int>, ви можете або використовувати конструктор, який також виконує функцію ініціалізації:

val arr = Array<Int>(10) { index -> 0 }  // full, verbose syntax
val arr = Array(10) { 0 }                // concise version

Або створіть, Array<Int?>щоб уникнути необхідності ініціалізувати кожне значення, але потім ви будете змушені мати справу з можливими nullзначеннями кожного разу, коли читаєте з масиву.

val arr = arrayOfNulls<Int>(10)

4
Це досить дурне рішення. Через це їм довелося створити новий клас для кожного примітивного типу ... Вони могли просто використовувати те саме, що і на Java.
розробник android

1
@androiddeveloper Який новий клас? int[]є IntArray, Integer[]є Array<Int>тощо, де цей загадковий новий клас? Це одне і те ж, лише синтаксис відрізняється. int[]це також клас, до речі.
Євген Печанець

1
@EugenPechanec Це цікаво. Вони кажуть, що це клас і що він має екземпляр, але також "екземпляри цього класу представлені як int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Отже, ці функції - це лише функції розширення, чи вони справжнього класу? І навіщо було потрібно мати "IntArray" та інші? Це все ще можна зробити за допомогою синтаксису Java.
розробник android

1
@EugenPechanec Але на Java int [] не є класом, чи не так? Це об’єкт, масив примітивів. Ви не можете досягти коду або продовжити його. Немає? Усі класи на Java мають свою велику літеру. Тут цього немає.
розробник android

1
@EugenPechanec Отже, на Kotlin це клас, тоді як на Java - ні. Тим не менше не розумієте, чому. Вони могли просто додати функції розширення, ні? Можливо, ви можете продовжити з IntArray? Щодо найменування, я знаю. Це просто конвенція, і хороша теж.
розробник Android

6

Варто зазначити, що використання *оператора spread ( ) на a varargповерне an IntArray. Якщо вам потрібно Array<Int>, ви можете конвертувати ваше IntArrayвикористання .toTypedArray().


1

Масиви в Kotlin - це класи (не "спеціальні" типи, такі як Java).

Кодлін stdlib пропонує спеціальні класи для примітивних масивів JVM з метою поліпшення інтеграції та продуктивності мови Java.

Основним правилом буде використання, Array<T>за винятком випадків, коли це спричиняє проблему при змішуванні з існуючим кодом Java або якщо його слід викликати з класів Java. Для запису мені ніколи не доводилось користуватися IntArray.

Ви можете перевірити документацію мови щодо цього питання тут: https://kotlinlang.org/docs/reference/basic-types.html#arrays


Я вважаю, ви маєте рацію щодо того, що завжди віддаєте перевагу Array <T> перед IntArray, мене хвилювали накладні витрати на бокс / розпаковування використання боксованого типу проти примітивного, але, схоже, Котлін досить розумний, щоб вирішити, чи можна використовувати примітив, чи ні . (Виправте мене, якщо я помиляюся) "На платформі Java номери фізично зберігаються як примітивні типи JVM, якщо нам не потрібне посилання на число з нульовим значенням (наприклад, Int?) Або дженерики. В останніх випадках номери вставляються в поля". Від kotlinlang.org/docs/reference/basic-types.html
FRR

@feresr не фахівець будь-яких засобів, але я думаю , що це тільки з посиланням на реалізації Int, Floatі т.д., враховуючи , що Котлин не має іншого типу для Booleanабо boolean. Що стосується масивів, я б припустив, що це Array<Int>буде відрізнятися від IntArray. Я особисто завжди користувався останнім, оскільки це мене ніколи не турбувало, але, можливо, Котлін має додаткову оптимізацію, про яку я не знаю. Якщо ви програмуєте виключно на kotlin, я не бачу жодного випадку, коли вам потрібно одне над іншим, але примітивний масив все одно може мати свої переваги.
Allan W

@AllanW теж не експерт, просто цікаво, я вважаю, що у Java є як примітиви, так і об'єкти в коробці, тому що ефективніше працювати з примітивами, чи не так? Звичайно, іноді вам дійсно потрібно працювати з об'єктом (анулювання / дженерики). Це виходить за рамки мого оригінального запитання, але мені цікаво, як Котлін вирішує це, націлюючись на JVM. Я намагаюся використовувати IntArray, коли це можливо (думаючи, що він використовує примітиви під капотом), але після коментаря @ jamming я вже не впевнений.
FRR

1
@feresr для мене, у документах Kotlin прямо вказано, що спеціальні екземпляри масиву існують, щоб уникнути накладних витрат на бокс. Мій висновок полягає в тому, що ці два, ймовірно, різні, і зрештою для розробника це стає таким самим, як прийняття рішення про те, чи потрібно використовувати Integer [] або int [] в Java.
Allan W

Я згоден, тоді прийнята відповідь може трохи ввести в оману для новачків, я відмічаю це як прийняту відповідь з цієї причини.
FRR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.