【问题标题】:IntArray vs Array<Int> in KotlinKotlin 中的 IntArray 与 Array<Int>
【发布时间】:2017-12-18 20:05:29
【问题描述】:

我不确定 Kotlin 中 IntArrayArray&lt;Int&gt; 之间的区别以及为什么我不能互换使用它们:

我知道IntArray 在定位JVM 时会转换为int[],但Array&lt;Int&gt; 会转换为什么?

此外,您还可以拥有String[]YourObject[]。为什么 Kotlin 有 {primitive}Array 类型的类,而几乎任何东西都可以排列成一个数组,而不仅仅是基元。

【问题讨论】:

标签: kotlin


【解决方案1】:

Array&lt;Int&gt;Integer[],而 IntArrayint[]。就是这样。

这意味着当您将Int 放入Array&lt;Int&gt; 时,它总是会被装箱(具体而言,使用Integer.valueOf() 调用)。在IntArray 的情况下,不会发生装箱,因为它会转换为Java 原始数组。


除了上述可能的性能影响之外,还需要考虑便利性。原始数组可以保持未初始化状态,它们将在所有索引处具有默认的0 值。这就是为什么IntArray 和其他原始数组的构造函数只接受大小参数:

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

相比之下,Array&lt;T&gt; 没有只接受大小参数的构造函数:它需要所有索引处的有效、非空 T 实例在创建后处于有效状态。对于Number 类型,这可能是默认的0,但无法创建任意类型T 的默认实例。

因此,在创建Array&lt;Int&gt; 时,您也可以使用带有初始化函数的构造函数:

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

或者创建一个Array&lt;Int?&gt; 以避免必须初始化每个值,但是以后每次从数组中读取时,您将不得不处理可能的null 值。

val arr = arrayOfNulls<Int>(10)

【讨论】:

  • 这是一个非常愚蠢的决定。因此,他们必须为每个原始类型创建一个新类......他们可以使用与 Java 相同的类。
  • @androiddeveloper 什么新类? int[]IntArrayInteger[]Array&lt;Int&gt;,等等,这个神秘的新班级在哪里?这是同一件事,只是语法不同。顺便说一句,int[] 也是类。
  • @EugenPechanec 这很有趣。他们说它是一个类并且它有一个实例,而且“这个类的实例表示为 int[]”:kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/…。那么,这些函数只是扩展函数,还是真正的类?为什么需要“IntArray”等?仍然可以使用 Java 语法来完成。
  • @EugenPechanec 但是在 Java 中, int[] 不是一个类,不是吗?它是一个对象,一个基元数组。您无法触及代码,或从代码扩展。不? Java 上的所有类的名称都有一个大写字母。这不是。
  • @EugenPechanec 所以在 Kotlin 上它是一个类,而在 Java 上它不是。仍然不明白为什么。他们可以只添加扩展功能,不是吗?您也许可以从 IntArray 扩展?关于命名,我知道。这只是惯例,也是一个很好的惯例。
【解决方案2】:

值得注意的是,在 vararg 上使用扩展 (*) 运算符将返回 IntArray。如果您需要Array&lt;Int&gt;,您可以使用.toTypedArray() 转换您的IntArray

【讨论】:

    【解决方案3】:

    Kotlin 中的数组是类(不是像 Java 这样的“特殊”类型)。

    Kotlin 的 stdlib 为 JVM 原始数组提供了特殊用途的类,以提高 Java 语言集成和性能。

    经验法则是使用Array&lt;T&gt;,除非它在与现有Java 代码混合时引起问题,或者应该从Java 类中调用。郑重声明,我从来不用IntArray

    您可以在此处查看有关此问题的语言文档:https://kotlinlang.org/docs/reference/basic-types.html#arrays

    【讨论】:

    • 我相信你总是偏爱 Array 而不是 IntArray 是对的,我担心使用盒装类型与原始类型的装箱/拆箱开销,但似乎 Kotlin 足够聪明,可以决定天气它可以使用或不使用原语。 (如果我错了,请纠正我)“在 Java 平台上,数字在物理上存储为 JVM 基本类型,除非我们需要一个可为空的数字引用(例如 Int?)或涉及泛型。在后一种情况下,数字被装箱了。”来自kotlinlang.org/docs/reference/basic-types.html
    • @feresr 无论如何都不是专家,但我认为这只是指IntFloat 等的实现,因为 Kotlin 没有 @ 的不同类型987654327@ 或boolean。在数组方面,我假设Array&lt;Int&gt;IntArray 不同。我个人一直使用后者,因为它从来没有打扰过我,但也许 Kotlin 有我不知道的额外优化。如果您仅在 kotlin 中编程,我看不到任何情况下您需要一个而不是另一个,但原始数组可能仍然有它的好处。
    • @AllanW 也不是专家,只是好奇,我相信 java 有原语和装箱对象,因为使用原语更有效,对吧?当然有时你真的需要使用对象(可空性/泛型)。这超出了我最初问题的范围,但我想知道 Kotlin 在针对 JVM 时如何处理这个问题。我尽可能尝试使用 IntArray(认为它在后台使用原语)但在 @jamming 评论之后我不确定了。
    • @feresr 对我来说,Kotlin 的文档明确指出特殊的数组实例是为了避免装箱开销。我的结论是两者可能不同,最终对开发人员来说,这与决定在 Java 中是使用 Integer[] 还是 int[] 是一样的。
    • 我同意,那么接受的答案可能会对新手产生一点误导,因此我将其取消标记为接受的答案。
    猜你喜欢
    • 2017-02-23
    • 2020-09-10
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 2017-04-17
    • 2016-06-10
    相关资源
    最近更新 更多