FloatArray vs Array<Float>:为什么它们不同



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

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

在Kotlin中,差异大多是隐藏的,所以为了解释,最好回到Java…

Java有九种基本类型(如果我计算正确的话)。其中八个直接持有一个值:booleanbyteshortcharintlongfloatdouble——这些被称为"基元"。另一种类型是引用,它可以指向对象或数组的实例。

因为在某些情况下,您需要将其中一个基元值作为对象传递,Java还提供了一些简单包装基元值的对象:java.lang.Booleanjava.lang.Byte等等。每个基元类型都有一个。

大多数代码直接使用基元,但有时传递对象引用很方便。(首先,基元是不可为null的,所以如果需要支持null,那么就需要对象引用。另一方面,像List这样的泛型代码和集合框架中的其他类只能处理对象引用。)

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

包装器与原始类型有着明显的区别——它们是大写的(在Integer的情况下,拼写不同)。在Java的早期版本中,它们是不可互换的;您需要在需要时显式包装(例如Int(someValue)和展开包装(例如,someReference.intValue())。Java5添加了"自动装箱",在许多情况下,编译器会为您执行此操作。这稍微模糊了区别,但大多数时候你仍然需要意识到这一点

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

var i: Int

它声明了一个Int值,该值将作为基元字段存储。但是:

var i: Int?

声明对整数包装器的引用。(这是因为基元是不可为null的,因此基元不能存储null值。)

这是一个实现细节:大多数时候,当你在写Kotlin时,你不需要意识到这一点。但这种区别在运行时仍然存在,数组是少数可见的情况之一:

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

  • CCD_ 23是对CCD_ 24对象的引用的数组。它更灵活,并且可以与使用Float[]类型的Java代码进行互操作。

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

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

关于Kotlin中数组的一些信息可在此处获得:https://kotlinlang.org/docs/basic-types.html#primitive-类型阵列

Kotlin还有一些类,它们表示基元类型的数组,而不需要装箱开销:ByteArray、ShortArray、IntArray等。这些类与Array类没有继承关系,但它们具有相同的方法和属性集。

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

看看FloatArray是如何在文档中声明的。它只是另一个类,与Array<T>类完全无关。当然,它们代表了非常相似的东西,不同的是,正如另一个答案所解释的那样,其中一个会框住Float值,而另一个不会。但从类型系统的角度来看,它们是完全不相关的。就好像我宣称:

class A
class B

并试图将CCD_ 37的实例传递给期望CCD_。

不过,有一些内置方法可以在这些类型之间进行转换:

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

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

最新更新