IntArray vs Array <Int> in Kotlin


91

Non sono sicuro di quale sia la differenza tra an IntArraye an Array<Int>in Kotlin e perché non posso usarli in modo intercambiabile:

mancata corrispondenza

So che si IntArraytraduce in int[]quando si targetizza il JVM, ma in cosa si Array<Int>traduce?

Inoltre, puoi anche avere String[]o YourObject[]. Perché Kotlin ha classi del tipo {primitive}Arrayquando praticamente qualsiasi cosa può essere organizzata in un array, non solo primitive.


1
La mia ipotesi è che Array<Int>compili in Integer[](se il compilatore non lo ottimizza)
Mibac


Sì, ha molto senso, grazie ad entrambi!
FRR

Risposte:


111

Array<Int>è un Integer[]sotto il cofano, mentre IntArrayè unint[] . Questo è tutto.

Ciò significa che quando metti un Intin un Array<Int>, sarà sempre inscatolato (in particolare, con una Integer.valueOf()chiamata). Nel caso di IntArray, non si verificherà alcun boxing, perché si traduce in un array primitivo Java.


Oltre alle possibili implicazioni sulle prestazioni di quanto sopra, c'è anche la comodità da considerare. Gli array primitivi possono essere lasciati non inizializzati e avranno 0valori predefiniti in tutti gli indici. Questo è il motivo IntArrayper cui e il resto degli array primitivi hanno costruttori che accettano solo un parametro di dimensione:

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

Al contrario, Array<T>non ha un costruttore che accetta solo un parametro size: ha bisogno di Tistanze valide e non nulle in tutti gli indici per essere in uno stato valido dopo la creazione. Per i Numbertipi, potrebbe essere un'impostazione predefinita 0, ma non è possibile creare istanze predefinite di un tipo arbitrarioT .

Quindi, quando crei un Array<Int>, puoi usare il costruttore che accetta anche una funzione di inizializzazione:

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

Oppure creane uno Array<Int?>per evitare di dover inizializzare ogni valore, ma in seguito sarai costretto a gestire i possibili nullvalori ogni volta che leggi dall'array.

val arr = arrayOfNulls<Int>(10)

4
Questa è una decisione abbastanza stupida. Per questo motivo, hanno dovuto creare una nuova classe per ogni tipo primitivo ... Potevano semplicemente usare lo stesso di Java.
sviluppatore Android

1
@androiddeveloper Quale nuova classe? int[]è IntArray, Integer[]è Array<Int>, e così via, dov'è questa misteriosa nuova classe? È la stessa cosa solo la sintassi è diversa. int[]è anche classe, tra l'altro.
Eugen Pechanec

1
@EugenPechanec Questo è interessante. Dicono che sia una classe e che abbia un'istanza, ma anche "le istanze di questa classe sono rappresentate come int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Quindi, quelle funzioni sono solo funzioni di estensione o sono di una vera classe? E perché era necessario disporre di "IntArray" e altri? Potrebbe ancora essere fatto usando la sintassi Java.
sviluppatore Android

1
@EugenPechanec Ma in Java, int [] non è una classe, no? È un oggetto, un array di primitive. Non puoi raggiungere il codice o estenderlo. No? Tutte le classi su Java hanno una lettera maiuscola nel nome. Qui non lo è.
sviluppatore Android

1
@EugenPechanec Quindi su Kotlin è una classe, mentre su Java non lo è. Ancora non capisco perché. Potrebbero semplicemente aggiungere funzioni di estensione, no? Puoi forse estendere da IntArray? Riguardo al nome, lo so. È solo la convenzione, e anche una buona.
sviluppatore Android

6

Vale la pena notare che l'uso *dell'operatore spread ( ) su a varargrestituirà un IntArray. Se hai bisogno di un Array<Int>, puoi convertire il tuo file IntArrayusing .toTypedArray().


1

Gli array in Kotlin sono classi (non tipi "speciali" come Java).

Lo stdlib di Kotlin fornisce classi speciali per array primitivi JVM al fine di migliorare l'integrazione e le prestazioni del linguaggio Java.

La regola pratica sarebbe quella di utilizzare Array<T>tranne se causa un problema durante la miscelazione con il codice Java esistente o se dovrebbe essere chiamato dalle classi Java. Per la cronaca, non ho mai dovuto usare IntArray.

Puoi controllare la documentazione del linguaggio riguardo a questo argomento qui: https://kotlinlang.org/docs/reference/basic-types.html#arrays


Credo che tu abbia ragione a preferire sempre Array <T> su IntArray, ero preoccupato per il sovraccarico di boxe / unboxing dell'utilizzo del tipo boxed vs primitivo, ma sembra che Kotlin sia abbastanza intelligente da decidere se può usare un primitivo o meno . (Correggimi se sbaglio) "Sulla piattaforma Java, i numeri vengono memorizzati fisicamente come tipi primitivi JVM, a meno che non sia necessario un riferimento a un numero nullable (ad es. Int?) O non siano coinvolti generici. In questi ultimi casi i numeri sono inscatolati." Da kotlinlang.org/docs/reference/basic-types.html
FRR

@feresr un esperto con qualsiasi mezzo, ma penso che si riferisce solo alle implementazioni di Int, Floatecc, dato che Kotlin non ha un tipo differente per Booleano boolean. In termini di array, presumo che Array<Int>sarebbe diverso da IntArray. Personalmente ho sempre usato quest'ultimo poiché non mi ha mai infastidito, ma forse Kotlin ha un'ottimizzazione aggiuntiva di cui non sono a conoscenza. Se stai programmando esclusivamente in kotlin, non vedo nessun caso in cui ne hai bisogno uno sull'altro, ma l'array primitivo potrebbe comunque avere i suoi vantaggi.
Allan W

@AllanW non è nemmeno un esperto, solo curioso, credo che java abbia sia primitive che oggetti in scatola perché è più efficiente lavorare con le primitive, giusto ?, ovviamente a volte hai davvero bisogno di lavorare con oggetti (nullability / generics). Questo esula dall'ambito della mia domanda originale, ma mi chiedo come Kotlin lo gestisca quando prende di mira la JVM. Cerco di usare IntArray ogni volta che è possibile (pensando che stia usando primitive sotto il cofano) ma dopo @ jamming comment non ne sono più sicuro.
FRR

1
@feresr per me, la documentazione di Kotlin afferma esplicitamente che le istanze di array speciali sono lì per evitare il sovraccarico di boxe. La mia conclusione è che i due sono probabilmente diversi, e alla fine per lo sviluppatore diventa lo stesso che decidere se si desidera utilizzare Integer [] o int [] in Java.
Allan W

Sono d'accordo, quindi la risposta accettata può essere un po 'fuorviante per i nuovi arrivati, deseleziono questa risposta come accettata per questo motivo.
FRR
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.