IntArray vs Array in Kotlin
我不确定IntArray和Array之间的区别在Kotlin中是什么,为什么我不能互换使用它们:
我知道以JVM为目标时IntArray会转换为int[],但是Array会转换为什么?
另外,您还可以具有String[]或YourObject[]。 为什么Kotlin拥有类型为{primitive}Array的类,而几乎所有东西都可以排列成数组,而不仅仅是原语。
-
我的猜测是Array编译为Integer[](如果编译器未对此进行优化)
-
见stackoverflow.com/questions/35253368/
-
是的,这很有意义,谢谢你们!
Array是引擎盖下的Integer[],而IntArray是int[]。而已。
这意味着,当将Int放入Array时,它将始终被装箱(特别是使用Integer.valueOf()调用)。在IntArray的情况下,将不会发生装箱,因为它会转换为Java基本数组。
除了上述可能对性能的影响外,还需要考虑一些便利。原始数组可以保留为未初始化,并且它们在所有索引处均具有默认的0值。这就是IntArray和其他原始数组具有仅采用size参数的构造函数的原因:
1 2
| val arr = IntArray(10)
println(arr.joinToString()) // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
相比之下,Array< T >没有仅采用size参数的构造函数:创建后,它在所有索引上都需要有效的非null T实例,以使其处于有效状态。对于Number类型,这可能是默认的0,但是无法创建任意类型T的默认实例。
因此,在创建Array时,您也可以使用带有初始化函数的构造函数:
1 2
| val arr = Array<Int>(10) { index -> 0 } // full, verbose syntax
val arr = Array(10) { 0 } // concise version |
或创建一个Array以避免必须初始化每个值,但是随后您每次从数组中读取数据时都会被迫处理可能的null值。
1
| val arr = arrayOfNulls<Int>(10) |
-
这是很愚蠢的决定。因此,他们必须为每种原始类型创建一个新类……他们可以使用与Java相同的类。
-
@androiddeveloper什么新类? int[]是IntArray,Integer[]是Array,依此类推,这个神秘的新类在哪里?只是语法不同而已。顺便说一句,int[]也是类。
-
@EugenPechanec这很有趣。他们说它是一个类,并且它有一个实例,但是"该类的实例也表示为int []":kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/。那么,这些功能仅仅是扩展功能,还是属于真实类?以及为什么需要有" IntArray"和其他?仍可以使用Java语法完成。
-
@androiddeveloper IntArray是带有真实构造函数IntArray(size)的真实类。那等于Java中的类int [](不要与int混淆)及其构造函数int [size]。数据结构相同,语法不同。 Kotlin中的方括号保留给get运算符调用。 Java使用方括号表示原始数组和对象数组。 Kotlin使用通用Array <>表示对象数组。基本数组保留有IntArray,FloatArray等。据我所知,还没有其他明智的方法。
-
@EugenPechanec但是在Java中,int []不是一个类,不是吗?它是一个对象,一组原语。您无法达到代码或从代码扩展。没有? Java上的所有类的名称均带有大写字母。这里不是。
-
@androiddeveloper正确,它不是类,int[]是类型。 int[0]是该类型的对象。 int[].class是类型Class的对象,是类Class的实例。"请注意,Java中的基元和数组没有类或接口,但它们是类型。"请参见类vy类型与对象。这就解释了为什么不能扩展基元和数组。 |||从技术上讲,您可以创建以小写字母开头的类(有些新手也可以),但请想象一下混乱。
-
@EugenPechanec所以在Kotlin上是一个类,而在Java上则不是。仍然不明白为什么。他们可以添加扩展功能,不是吗?您也许可以从IntArray扩展?关于命名,我知道。这只是约定,也是一个好的约定。
-
@androiddeveloper没错,IntArray是"一个整数数组。以JVM为目标时,此类的实例表示为int[]。"参见kdoc。举例说明这种扩展功能。返回类型是什么,接收者是什么类型?请记住,我们需要能够区分编译为int[]和Integer[]的类型。
-
@EugenPechanec我不明白你的意思。您在问我什么扩展功能?如果是这样,它只是一种调用Java静态函数的方式,就好像调用对象本身一样。例如,我可以在某个数组/列表类上创建函数swap(pos1,pos2)而不扩展它,而不是自己编写一个静态函数swap(list,pos1,pos2)。这是一个非常不错的功能,可能有点令人困惑,好像在类实现中确实拥有此功能,但您却没有。
-
让我们继续聊天中的讨论。
值得注意的是,在vararg上使用传播(*)运算符将返回IntArray。如果需要Array,则可以使用.toTypedArray()转换IntArray。
Kotlin中的数组是类(不是Java的"特殊"类型)。
Kotlin的stdlib为JVM基本数组提供了特殊用途的类,以改善Java语言的集成和性能。
经验法则是使用Array< T >,除非它在与现有Java代码混合时会引起问题,或者应从Java类中调用。出于记录,我从来不必使用IntArray。
您可以在以下位置查看有关此问题的语言文档:https://kotlinlang.org/docs/reference/basic-types.html#arrays
-
我相信您总是对Array < T >胜过IntArray是正确的,我担心使用盒装类型vs原语的装箱/拆箱开销,但是Kotlin似乎足够聪明,可以决定是否可以使用原语。 (如果我错了,请纠正我)"在Java平台上,数字实际上存储为JVM基本类型,除非我们需要可为空的数字引用(例如Int?)或涉及泛型。在后一种情况下,数字会被装箱。"来自kotlinlang.org/docs/reference/basic-types.html
-
@feresr绝对不是专家,但是我认为这只是指Int,Float等的实现,因为Kotlin对于Boolean或Boolean没有不同的类型。在数组方面,我假设Array与IntArray不同。我个人一直使用后者,因为它从来没有打扰过我,但也许Kotlin还有我不知道的其他优化。如果您仅使用kotlin进行编程,那么我看不到任何情况都需要一个,但是原始数组可能仍然有其好处。
-
@AllanW也不是专家,只是好奇,我相信Java同时具有基元和装箱的对象,因为它可以更有效地使用基元,对吗?当然,有时您确实需要使用对象(可空性/泛型)。这超出了我最初提出的问题的范围,但是我想知道Kotlin在针对JVM时是如何处理的。我尝试尽可能使用IntArray(认为它是在幕后使用基元),但是在@ jamming comment Im之后,我不
-
@feresr对我来说,Kotlins文档明确声明特殊数组实例在那里,以避免装箱开销。我得出的结论是,两者可能有所不同,最终对开发人员而言,它与决定是否要在Java中使用Integer []或int []一样。
-
我同意,那么接受的答案可能会误导新来者,出于这个原因,我未将其标记为接受的答案。
-
@AllanW当您使用JNI时,必须使用IntArray。向Java和从Java传递j Array(jintArray,jdoubleArray等)需要在Java端处理原始值数组,因此不可避免地使用IntArray,并且这是这样做的唯一方法。 Array 在本机端被视为Jobject。