IntArray vs Array <Int> dans Kotlin

88

Je ne sais pas quelle est la différence entre un IntArrayet un Array<Int>dans Kotlin et pourquoi je ne peux pas les utiliser de manière interchangeable:

manque de correspondance

Je sais que cela se IntArraytraduit par le int[]ciblage de JVM, mais qu'est-ce que cela signifie Array<Int>?

En outre, vous pouvez également avoir String[]ou YourObject[]. Pourquoi Kotlin a des classes du type {primitive}Arrayquand à peu près tout peut être organisé dans un tableau, pas seulement les primitives.

FRR
la source
1
Je suppose que Array<Int>compile vers Integer[](si le compilateur n'optimise pas cela)
Mibac
Oui, cela a beaucoup de sens, merci à vous deux!
FRR

Réponses:

107

Array<Int>est un Integer[]sous le capot, tandis que IntArrayest un int[]. C'est ça.

Cela signifie que lorsque vous mettez un Intdans un Array<Int>, il sera toujours encadré (spécifiquement, avec un Integer.valueOf()appel). Dans le cas de IntArray, aucune boxe ne se produira, car elle se traduit par un tableau primitif Java.


Outre les implications possibles de ce qui précède sur les performances, il convient également de prendre en compte la commodité. Les tableaux primitifs peuvent être laissés non initialisés et ils auront des 0valeurs par défaut à tous les index. C'est pourquoi IntArrayet le reste des tableaux primitifs ont des constructeurs qui ne prennent qu'un paramètre de taille:

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

En revanche, Array<T>n'a pas de constructeur qui ne prend qu'un paramètre de taille: il a besoin d' Tinstances valides non nulles à tous les index pour être dans un état valide après la création. Pour les Numbertypes, cela peut être une valeur par défaut 0, mais il n'y a aucun moyen de créer des instances par défaut d'un type arbitraire T.

Ainsi, lors de la création d'un Array<Int>, vous pouvez soit utiliser le constructeur qui prend également une fonction d'initialisation:

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

Ou créez un Array<Int?>pour éviter d'avoir à initialiser chaque valeur, mais vous serez ensuite obligé de gérer les nullvaleurs possibles chaque fois que vous lirez dans le tableau.

val arr = arrayOfNulls<Int>(10)
zsmb13
la source
4
C'est une décision assez stupide. Pour cette raison, ils ont dû créer une nouvelle classe pour chaque type primitif ... Ils pouvaient simplement utiliser la même chose que sur Java.
développeur android
1
@androiddeveloper Quelle nouvelle classe? int[]est IntArray, Integer[]est Array<Int>, et ainsi de suite, où est cette nouvelle classe mystérieuse? C'est la même chose, seule la syntaxe est différente. int[]est aussi classe, d'ailleurs.
Eugen Pechanec
1
@EugenPechanec C'est intéressant. Ils disent que c'est une classe et qu'elle a une instance, mais aussi "les instances de cette classe sont représentées comme int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Alors, ces fonctions sont-elles juste des fonctions d'extension, ou sont-elles d'une vraie classe? Et pourquoi était-il nécessaire d'avoir "IntArray", et d'autres? Cela pourrait encore être fait en utilisant la syntaxe Java.
développeur android
1
@EugenPechanec Mais en Java, int [] n'est pas une classe, non? C'est un objet, un tableau de primitives. Vous ne pouvez pas accéder à son code ni en prolonger. Non? Toutes les classes sur Java ont une lettre majuscule à leur nom. Ici non.
développeur android
1
@EugenPechanec Donc sur Kotlin c'est une classe, alors que sur Java ce n'est pas le cas. Je ne comprends toujours pas pourquoi. Ils pourraient simplement ajouter des fonctions d'extension, non? Vous pouvez peut-être étendre d'IntArray? À propos de la dénomination, je sais. C'est juste la convention, et une bonne aussi.
développeur android
6

Il est à noter que l'utilisation de l' *opérateur spread ( ) sur a varargrenverra un fichier IntArray. Si vous avez besoin d'un Array<Int>, vous pouvez convertir votre IntArrayutilisation .toTypedArray().

Eran Boudjnah
la source
1

Les tableaux de Kotlin sont des classes (et non des types "spéciaux" comme Java).

Le stdlib de Kotlin fournit des classes à usage spécial pour les tableaux primitifs JVM afin d'améliorer l'intégration et les performances du langage Java.

La règle d'or serait à utiliser Array<T>sauf si cela pose un problème lors du mélange avec du code Java existant, ou doit être appelé à partir de classes Java. Pour mémoire, je n'ai jamais eu à m'en servir IntArray.

Vous pouvez consulter la documentation du langage à ce sujet ici: https://kotlinlang.org/docs/reference/basic-types.html#arrays

jaguililla
la source
Je pense que vous avez raison de toujours favoriser Array <T> par rapport à IntArray, j'étais préoccupé par la surcharge de boxe / déballage liée à l'utilisation du type en boîte par rapport au primitif, mais il semble que Kotlin soit assez intelligent pour décider de la météo, il peut utiliser un primitif ou non . (Corrigez-moi si je me trompe) "Sur la plate-forme Java, les nombres sont physiquement stockés en tant que types primitifs JVM, à moins que nous ayons besoin d'une référence de nombre Nullable (par exemple Int?) Ou des génériques sont impliqués. Dans ces derniers cas, les nombres sont encadrés. De kotlinlang.org/docs/reference/basic-types.html
FRR
@feresr pas un expert par tout moyen, mais je pense que c'est seulement en se référant aux implémentations Int, Floatetc., étant donné que Kotlin ne dispose pas d' un type différent pour Booleanou boolean. En termes de tableaux, je suppose que cela Array<Int>serait différent de IntArray. J'ai personnellement toujours utilisé ce dernier car cela ne m'a jamais dérangé, mais peut-être que Kotlin a une optimisation supplémentaire dont je ne suis pas au courant. Si vous programmez uniquement en kotlin, je ne vois aucun cas où vous avez besoin de l' un par rapport à l'autre, mais le tableau primitif peut toujours avoir ses avantages.
Allan W
@AllanW n'est pas non plus un expert, juste curieux, je pense que java a à la fois des primitives et des objets encadrés car il est plus efficace de travailler avec des primitives, n'est-ce pas? Cela sort du cadre de ma question initiale, mais je me demande comment Kotlin gère cela lorsqu'il cible la JVM. J'essaie d'utiliser IntArray autant que possible (en pensant qu'il utilise des primitives sous le capot) mais après @ jamming comment je ne suis plus sûr.
FRR
1
@feresr pour moi, la documentation de Kotlin indique explicitement que les instances de tableau spéciales sont là pour éviter la surcharge de boxe. Ce que je retiens, c'est que les deux sont probablement différents, et en fin de compte, pour le développeur, cela revient à décider si vous voulez utiliser Integer [] ou int [] en Java.
Allan W
Je suis d'accord, alors la réponse acceptée peut être un peu trompeuse pour les nouveaux arrivants, je ne la marque pas comme la réponse acceptée pour cette raison.
FRR