FloatArray 与 Array<Float>:它们为何不同

FloatArray vs Array<Float>: why are they different

如果答案显而易见,我深表歉意,但我不明白。我有一个接受 FloatArray 的函数,所以我向它传递了 Array<Float> 但它拒绝了它!我认为 FloatArray 只是另一种创建 Array<Float> 的方式。有什么区别?

有关 Kotlin 中数组的一些信息可在此处获得:https://kotlinlang.org/docs/basic-types.html#primitive-type-arrays

Kotlin also has classes that represent arrays of primitive types without boxing overhead: ByteArray, ShortArray, IntArray, and so on. These classes have no inheritance relation to the Array class, but they have the same set of methods and properties.

所以FloatArrayArray<Float>不一样,区别是第一个没有装箱开销。

看看 FloatArray is declared in the documentation. It is just another class, not related to the Array<T> class 怎么样。当然,它们代表非常相似的东西,不同之处在于它们中的一个会装箱 Float 值,而另一个则不会,正如另一个答案所解释的那样。但是从类型系统的角度来看,它们是完全不相关的。就好像我声明:

class A
class B

并尝试将 A 的实例传递给需要 B 的参数。

虽然有内置方法可以在这些类型之间进行转换:

floatArrayOf(1f,2f,3f).toTypedArray() // FloatArray to Array<Float>
arrayOf(1f,2f,3f).toFloatArray() // Array<Float> to FloatArray

只是它们之间没有隐式转换,因为它们是不相关的类型,不像你有 subclasses 和 superclasses 例如。

简短回答:一个是基元数组,另一个是对 Float 个对象的引用数组。

在 Kotlin 中,差异大部分对您是隐藏的,所以解释最好回到 Java…

Java 有九种基本类型(如果我没数错的话)。其中八个直接持有一个值:booleanbyteshortcharintlongfloat、和 double — 那些被称为“原语”。另一种类型是 reference,它可以指向对象或数组的实例。

因为有些情况下您需要将这些原始值之一作为对象传递,Java 还提供了一些简单地包装原始值的对象:java.lang.Booleanjava.lang.Byte, 等等。每种原始类型都有一个。

大多数代码直接使用基元,但有时传递对象引用会很方便。 (一方面,原语不可为空,因此如果您需要支持空,则需要一个对象引用。”另一方面,通用代码,例如 List 和另一个 类集合框架只能处理对象引用。)

然而,对象包装器的效率较低,因为每个实例都是一个完整的对象并占用一定数量的内存(例如 16-32 字节,具体取决于 Java 运行时)——这是除了对它的引用的大小(可能是 8 个字节)。 JVM 缓存 commonly-used 包装器(例如布尔值的 true 和 false,以及一些小数字),但对于其他任何东西,您将在堆上创建新对象。

包装器与原始类型明显不同——它们是大写的(而且,在 Integer 的情况下,拼写不同)。在 Java 的早期版本中,它们是不可互换的;您需要在需要时显式包装(例如 Int(someValue) 和解包(例如 someReference.intValue())。 Java 5 添加了“自动装箱”,在许多情况下,编译器会为您执行此操作。 这模糊了区别有点大,但大多数时候还是需要注意的。

Kotlin 的一个好处是它消除了一些 Java 不必要的复杂性。它执行此操作的方法之一是几乎完全隐藏这种区别。 Kotlin 语言没有原语:一切看起来都像一个对象。然而,出于效率的原因,编译后的 Kotlin 在可能的情况下使用了“底层”原语。例如:

var i: Int

这声明了一个 Int 值 — 它将被存储为原始字段。然而:

var i: Int?

这声明了对整数包装器的引用。 (这是因为原语不可为空,因此原语不能存储空值。)

这是一个实现细节:大多数时候,当您编写 Kotlin 时,您不需要知道这一点。但是区别在运行时仍然存在,数组是它变得可见的罕见情况之一:

  • FloatArray 是基元数组。它使用最少的内存,并与使用 float[] 类型的 Java 代码互操作。

  • Array<Float> 是对 Float 个对象的引用数组。它更灵活,并且可以与使用 Float[] 类型的 Java 代码互操作。

所以你可以看出这是两种不同的类型,尽管它们做的事情相似。

如果您要与现有代码进行互操作,这将控制您应该使用哪一个。如果您正在编写新代码,那么您可以选择:FloatArray 可能更高效并且使用更少的内存 — 但 Array<Float> 往往在其他代码中得到更好的支持(这可能能够仅通过接受泛型 Array 来处理所有相关类型,而不必支持 FloatArray and IntArray and LongArray 和所有其他人)。