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.
所以FloatArray
和Array<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 有九种基本类型(如果我没数错的话)。其中八个直接持有一个值:boolean
、byte
、short
、char
、int
、long
、float
、和 double
— 那些被称为“原语”。另一种类型是 reference,它可以指向对象或数组的实例。
因为有些情况下您需要将这些原始值之一作为对象传递,Java 还提供了一些简单地包装原始值的对象:java.lang.Boolean
、java.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
和所有其他人)。
如果答案显而易见,我深表歉意,但我不明白。我有一个接受 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.
所以FloatArray
和Array<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 有九种基本类型(如果我没数错的话)。其中八个直接持有一个值:boolean
、byte
、short
、char
、int
、long
、float
、和 double
— 那些被称为“原语”。另一种类型是 reference,它可以指向对象或数组的实例。
因为有些情况下您需要将这些原始值之一作为对象传递,Java 还提供了一些简单地包装原始值的对象:java.lang.Boolean
、java.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
和所有其他人)。