IntArray vs Array <Int> in Kotlin

88

Ich bin mir nicht sicher, was der Unterschied zwischen einem IntArrayund einem Array<Int>in Kotlin ist und warum ich sie nicht austauschbar verwenden kann:

Missmatch

Ich weiß, dass dies beim Targeting auf IntArrayübersetzt wird , aber was bedeutet das?int[]JVMArray<Int>

Sie können auch String[]oder haben YourObject[]. Warum Kotlin Klassen dieses Typs hat, {primitive}Arraywenn so ziemlich alles in einem Array angeordnet werden kann, nicht nur Grundelemente.

FRR
quelle
1
Ich vermute, dass Array<Int>kompiliert wird Integer[](wenn der Compiler dies nicht optimiert)
Mibac
Ja, das macht sehr viel Sinn, danke euch beiden!
FRR

Antworten:

107

Array<Int>ist ein Integer[]unter der Haube, während IntArrayist ein int[]. Das ist es.

Dies bedeutet , dass , wenn Sie ein setzen Intin ein Array<Int>, wird es immer (genauer gesagt, mit einem boxed wird Integer.valueOf()Anruf). Im Fall von IntArraytritt kein Boxen auf, da es in ein primitives Java-Array übersetzt wird.


Abgesehen von den möglichen Auswirkungen der oben genannten Leistung auf die Leistung ist auch die Bequemlichkeit zu berücksichtigen. Primitive Arrays können nicht initialisiert werden und haben 0an allen Indizes Standardwerte . Aus diesem Grund haben IntArrayder Rest der primitiven Arrays Konstruktoren, die nur einen Größenparameter annehmen:

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

Im Gegensatz dazu Array<T>gibt es keinen Konstruktor, der nur einen Größenparameter akzeptiert: Er benötigt gültige Nicht-Null- TInstanzen an allen Indizes, um nach der Erstellung in einem gültigen Zustand zu sein. Für NumberTypen kann dies ein Standard sein 0, es gibt jedoch keine Möglichkeit, Standardinstanzen eines beliebigen Typs zu erstellen T.

Wenn Sie also eine erstellen Array<Int>, können Sie entweder den Konstruktor verwenden, der auch eine Initialisierungsfunktion übernimmt:

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

Oder erstellen Sie eine Array<Int?>, um zu vermeiden, dass jeder Wert initialisiert werden muss. Später müssen Sie jedoch nulljedes Mal, wenn Sie aus dem Array lesen, mit möglichen Werten umgehen .

val arr = arrayOfNulls<Int>(10)
zsmb13
quelle
4
Das ist eine ziemlich dumme Entscheidung. Aus diesem Grund mussten sie für jeden primitiven Typ eine neue Klasse erstellen ... Sie konnten dieselbe wie auf Java verwenden.
Android-Entwickler
1
@androiddeveloper Welche neue Klasse? int[]ist IntArray, Integer[]ist Array<Int>und so weiter, wo ist diese mysteriöse neue Klasse? Es ist dasselbe, nur die Syntax ist unterschiedlich. int[]ist übrigens auch klasse.
Eugen Pechanec
1
@ EugenPechanec Das ist interessant. Sie sagen, es ist eine Klasse und sie hat eine Instanz, aber auch "Instanzen dieser Klasse werden als int [] dargestellt": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Sind diese Funktionen also nur Erweiterungsfunktionen oder gehören sie zu einer echten Klasse? Und warum musste es "IntArray" und andere geben? Könnte immer noch nur mit Java-Syntax durchgeführt werden.
Android-Entwickler
1
@EugenPechanec Aber in Java ist int [] keine Klasse, oder? Es ist ein Objekt, eine Reihe von Grundelementen. Sie können den Code nicht erreichen oder von ihm aus erweitern. Nein? Alle Klassen unter Java haben einen Großbuchstaben am Namen. Hier ist es nicht.
Android-Entwickler
1
@EugenPechanec Auf Kotlin ist es also eine Klasse, auf Java nicht. Ich verstehe immer noch nicht warum. Sie könnten einfach Erweiterungsfunktionen hinzufügen, nein? Sie können vielleicht von IntArray verlängern? Über die Benennung weiß ich Bescheid. Es ist nur die Konvention und auch eine gute.
Android-Entwickler
6

Es ist erwähnenswert, dass die Verwendung des *Operatorspread ( ) für a eine varargzurückgibt IntArray. Wenn Sie eine benötigen Array<Int>, können Sie Ihre IntArrayVerwendung konvertieren .toTypedArray().

Eran Boudjnah
quelle
1

Arrays in Kotlin sind Klassen (keine "speziellen" Typen wie Java).

Kotlins stdlib bietet spezielle Klassen für primitive JVM-Arrays, um die Integration und Leistung der Java-Sprache zu verbessern.

Als Faustregel gilt die Verwendung, es sei Array<T>denn, sie verursacht beim Mischen mit vorhandenem Java-Code ein Problem oder sollte aus Java-Klassen aufgerufen werden. Für die Aufzeichnung musste ich nie verwenden IntArray.

Sie können die diesbezügliche Dokumentation der Sprache hier einsehen : https://kotlinlang.org/docs/reference/basic-types.html#arrays

Jaguililla
quelle
Ich glaube, Sie haben Recht damit, Array <T> immer gegenüber IntArray zu bevorzugen. Ich war besorgt über den Box- / Unboxing-Aufwand bei der Verwendung des Box-Typs im Vergleich zum Primitiv, aber Kotlin scheint klug genug zu sein, um zu entscheiden, ob ein Primitiv verwendet werden kann oder nicht . (Korrigieren Sie mich, wenn ich falsch liege.) "Auf der Java-Plattform werden Zahlen physisch als primitive JVM-Typen gespeichert, es sei denn, wir benötigen eine nullfähige Zahlenreferenz (z. B. Int?) Oder es handelt sich um Generika. In letzteren Fällen werden Zahlen in ein Kästchen gesetzt." Von kotlinlang.org/docs/reference/basic-types.html
FRR
@feresr kein Experte mit allen Mitteln, aber ich denke , dass nur unter Bezugnahme auf die Implementierungen Int, Floatusw., da Kotlin nicht eine andere Art für hat Booleanoder boolean. In Bezug auf Arrays würde ich davon ausgehen, dass sich Array<Int>das von unterscheiden würde IntArray. Letzteres habe ich persönlich immer verwendet, da es mich nie gestört hat, aber vielleicht hat Kotlin zusätzliche Optimierungen, die mir nicht bekannt sind. Wenn Sie ausschließlich in Kotlin programmieren, sehe ich keinen Fall, in dem Sie einen über den anderen benötigen , aber das primitive Array kann dennoch seine Vorteile haben.
Allan W
@AllanW auch kein Experte, nur neugierig, ich glaube, Java hat sowohl Primitive als auch Boxed-Objekte, weil es effizienter ist, mit Primitiven zu arbeiten, oder? Natürlich muss man manchmal wirklich mit Objekten arbeiten (Nullability / Generics). Dies geht aus dem Rahmen meiner ursprünglichen Frage heraus, aber ich frage mich, wie Kotlin damit umgeht, wenn er auf die JVM abzielt. Ich versuche, IntArray zu verwenden, wann immer es möglich ist (ich denke, dass Primitive unter der Haube verwendet werden), aber nach dem @ jamming-Kommentar bin ich mir nicht mehr sicher.
FRR
1
@feresr für mich heißt es in Kotlins Dokumenten ausdrücklich, dass die speziellen Array-Instanzen vorhanden sind, um den Box-Overhead zu vermeiden. Meiner Meinung nach sind die beiden wahrscheinlich unterschiedlich, und am Ende wird es für den Entwickler gleichbedeutend mit der Entscheidung, ob Sie Integer [] oder int [] in Java verwenden möchten.
Allan W
Ich stimme zu, dann kann die akzeptierte Antwort für Neuankömmlinge etwas irreführend sein. Ich markiere dies aus diesem Grund nicht als akzeptierte Antwort.
FRR