121

I'm not sure what the difference between an IntArray and an Array<Int> is in Kotlin and why I can't used them interchangeably:

missmatch

I know that IntArray translates to int[] when targeting the JVM, but what does Array<Int> translate to?

Also, you can also have String[] or YourObject[]. Why Kotlin has classes of the type {primitive}Array when pretty much anything can be arranged into an array, not only primitives.

frankelot
  • 13,666
  • 16
  • 54
  • 89

3 Answers3

163

Array<Int> is an Integer[] under the hood, while IntArray is an int[]. That's it.

This means that when you put an Int in an Array<Int>, it will always be boxed (specifically, with an Integer.valueOf() call). In the case of IntArray, no boxing will occur, because it translates to a Java primitive array.


Other than the possible performance implications of the above, there's also convenience to consider. Primitive arrays can be left uninitialized and they will have default 0 values at all indexes. This is why IntArray and the rest of the primitive arrays have constructors that only take a size parameter:

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

In contrast, Array<T> doesn't have a constructor that only takes a size parameter: it needs valid, non-null T instances at all indexes to be in a valid state after creation. For Number types, this could be a default 0, but there's no way to create default instances of an arbitrary type T.

So when creating an Array<Int>, you can either use the constructor that takes an initializer function as well:

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

Or create an Array<Int?> to avoid having to initialize every value, but then you'll be later forced to deal with possible null values every time you read from the array.

val arr = arrayOfNulls<Int>(10)
zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • 6
    This is quite stupid decision. Because of this, they had to create a new class for each primitive type... They could just use the same as on Java. – android developer Nov 23 '17 at 07:51
  • 4
    @androiddeveloper What new class? `int[]` is `IntArray`, `Integer[]` is `Array`, and so on, where's this mysterious new class? It's the same thing only syntax is different. `int[]` is also class, by the way. – Eugen Pechanec Jan 17 '18 at 16:13
  • 3
    @EugenPechanec This is interesting. They say it's a class and that it has an instance, but also " instances of this class are represented as int[]" : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/index.html . So, are those functions just extension functions, or are they of a real class? And why was it needed to have "IntArray", and others ? Could still just be done using Java syntax. – android developer Jan 17 '18 at 20:25
  • @androiddeveloper IntArray is a real class with a real constructor IntArray(size). That's equal to class int[] (don't confuse with int) and it's constructor int[size] in Java. The data structure is the same, the syntax is different. Square brackets in Kotlin are reserved for the get operator call. Java uses square brackets for arrays of primitives and arrays of objects. Kotlin uses generic Array<> to represent arrays of objects. Arrays of primitives were left with IntArray, FloatArray, etc. As far as I can see there was no other sensible way left. – Eugen Pechanec Jan 17 '18 at 21:18
  • 1
    @EugenPechanec But in Java, int[] is not a class, no? It's an object, an array of primitives. You can't reach is code, or extend from it. No? All classes on Java have an uppercase letter at their name. Here it's not. – android developer Jan 18 '18 at 07:47
  • @androiddeveloper Correct, it's not a class, `int[]` is a *type*. `int[0]` is an *object* of that type. `int[].class` is an object of type `Class` and an *instance* of class `Class`. *"Note that primitives and arrays in Java do not have a class or interface but they are types."* See [Class vy Type vs Object](https://blog.kotlin-academy.com/programmer-dictionary-class-vs-type-vs-object-e6d1f74d1e2e). That explains why you can't extend primitives and arrays. ||| You can technically create classes starting with lowercase letter (and some newcomers do) but imagine the mess. – Eugen Pechanec Jan 18 '18 at 10:29
  • 1
    @EugenPechanec So on Kotlin it's a class, while on Java it's not. Still don't get why though. They could just add extension functions, no? You can perhaps extend from IntArray? About the naming, I know. It's just the convention, and a good one too. – android developer Jan 18 '18 at 12:11
  • @androiddeveloper That's right, `IntArray` is *"An array of ints. When targeting the JVM, instances of this class are represented as `int[]`."* [See kdoc.](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/index.html) Give an example of such extension function. What's the return type and what type is the receiver? Remember, we need to be able to distinguish between types that compile to `int[]` and `Integer[]`. – Eugen Pechanec Jan 18 '18 at 12:39
  • 1
    @EugenPechanec I don't understand what you mean. You are asking me what's extension function? If so, it's just a way to call a Java static function as if it's of the object itself. For example, I could create a function `swap(pos1,pos2)` on some array/list class, without extending it, instead of writing a static function myself `swap(list,pos1,pos2)` . It's a very nice feature, which might be a bit confusing to show as if you really have this function inside the class implementation, yet you don't. – android developer Jan 18 '18 at 13:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/163417/discussion-between-eugen-pechanec-and-android-developer). – Eugen Pechanec Jan 18 '18 at 13:48
  • 1
    The performance difference between `val t = IntArray(10_000_000) { it }` and `val t = Array(10_000_000) { it }` is 20 milliseconds vs 2.5 seconds on a 2019 mbp. – Καrτhικ Mar 11 '20 at 16:44
14

It is worth noting that using the spread (*) operator on a vararg will return an IntArray. If you need an Array<Int>, you can convert your IntArray using .toTypedArray().

Eran Boudjnah
  • 1,228
  • 20
  • 22
2

Arrays in Kotlin are classes (not "special" types like Java).

Kotlin's stdlib provides special purpose classes for JVM primitive arrays in order to improve Java language integration and performance.

The rule of thumb would be to use Array<T> except if it cause a problem when mixing with existing Java code, or should be called from Java classes. For the record, I never had to use IntArray.

You can check the Language's documentation regarding this matter here: https://kotlinlang.org/docs/reference/basic-types.html#arrays

jaguililla
  • 1,916
  • 18
  • 21
  • I believe you are right about always favouring Array over IntArray, I was worried about the boxing/unboxing overhead of using the boxed type vs primitive, but it seems that Kotlin is smart enough to decide weather it can use a primitive or not. (Correct me if I'm wrong) "On the Java platform, numbers are physically stored as JVM primitive types, unless we need a nullable number reference (e.g. Int?) or generics are involved. In the latter cases numbers are boxed." From https://kotlinlang.org/docs/reference/basic-types.html – frankelot Jul 14 '17 at 00:02
  • @feresr not an expert by any means, but I think that is only referring to the implementations of `Int`, `Float`, etc, given that Kotlin doesn't have a different type for `Boolean` or `boolean`. In terms of arrays, I would assume that `Array` would differ from `IntArray`. I've personally always used the latter since it's never bothered me, but maybe Kotlin has additional optimization that I'm not aware of. If you're programming solely in kotlin, I don't see any case where you _need_ one over the other, but the primitive array may still have its benefits. – Allan W Jul 14 '17 at 01:04
  • @AllanW not an expert either, just curious, I believe java has both primitives and boxed objects because it's more efficient to work with primitives right?, of course sometimes you really need to work with object (nullability/generics). This goes out of the scope of my original question but I wonder how Kotlin handles this when targeting the JVM. I try to use IntArray whenever possible (thinking that it's using primitives under the hood) but after @ jamming comment I'm not sure anymore. – frankelot Jul 14 '17 at 02:44
  • 1
    @feresr to me, Kotlin's docs explicitly states that the special array instances are there to avoid the boxing overhead. My takeaway is that the two are likely different, and in the end to the developer it becomes the same as deciding whether you want to use Integer[] or int[] in Java. – Allan W Jul 14 '17 at 03:06
  • I agree, then the accepted answer can be a tad misleading to newcomers, I'm unmarking this as the accepted answer for this reason. – frankelot Jul 14 '17 at 03:30
  • @AllanW One case in which you are forced to use IntArray is when you are using JNI. Passing jArray (jintArray, jdoubleArray, etc) to and from Java requires handling an array of primitive values in the Java side, thus the use of IntArray is unavoidable and is the only way of doing this. An Array is seen on the native side as an jobject. – Jesús Barrera Jan 15 '19 at 19:03