我最初开始写这篇文章是因为我尝试了一些反射代码,并认为我发现了一些有趣的东西。可惜,事实并非如此。相反,它只是Kotlin的一个基本特性,我还不需要使用或关注它。虽然这篇文章并没有如我所愿,但我仍然认为它是一个很好的小帖子,可以让这个主题变得清晰一些。
在Java中,存在基本类型及其包装版本的概念。由于自动装箱和拆箱,类型可以在其原始版本和包装版本之间互换。换句话说,在大多数情况下,您可以使用a long
代替a Long
或a Long
代替a long
。如果您没有注意到最后一句中的大写字母在哪里,那么我想它可能看起来很混乱。那句话的措辞也很关键。更具体地说,声明“在大多数情况下”。
尝试互换原始数组和已包装的(宾语)数组。 例如,
public class PrimitiveArrays {
public static void main(String args[]) {
Long[] longArray = new Long[] {1L, 2L, 3L};
takesInPrimitiveLongArray(longArray);
}
static void takesInPrimitiveLongArray(long[] array) {}
}
这不起作用,尝试对其进行编译会产生以下错误:
error: incompatible types: Long[] cannot be converted to long[]
takesInPrimitiveLongArray(longArray);
切换方法以接受长[]并传递长[]出于同样的原因也将无法编译。 这并不是大多数Java开发人员都会感兴趣的东西,但有助于为本文的实际内容奠定基础。
Kotlin需要为您提供Java原始数组的等效功能。 但是,Kotlin不允许您使用与Java相同的语法来定义数组。 在Kotlin中,初始化数组看起来像:
val array = Array(3)
// or
val array: Array = arrayOf(1,2,3)
您可以看到的事实数组使用泛型应强调它不是原始数组。 在Java和Kotlin中,这都是事实,即泛型类型不能是基元。 否则,可以将其切换为数组
这种情况在阵列上是很独特的。 科特林长本身使用可以编译为长要么长在JVM字节码中。 编译的类型取决于字段的可为空性。 数组更明确,因此编译时它们的类型不会改变。
为了避免这种情况,Kotlin提供了一些选择,这些类在向下编译为JVM字节码时变为原始数组。
这些类包括:
Kotlin | Java |
---|---|
ByteArray | byte[] |
CharArray | char[] |
ShortArray | short[] |
IntArray | int[] |
LongArray | long[] |
DoubleArray | double[] |
FloatArray | float[] |
BooleanArray | boolean[] |
这些类也可以在Kotlin和Java之间互换,而无需付出任何额外的努力。
作为最后一个证据,向您展示Kotlin中原始数组与包装式/对象数组之间的区别,我想向您展示一些Kotlin代码,这些代码已转换为Java对应的代码:
@file:JvmName("PrimitiveArrays")
package dev.lankydan
fun main(args: Array) {
// long and Long arrays
val longArray = longArrayOf(1,2,3,4)
val arrayOfLongs = arrayOf(1,2,3,4)
// int and Integer arrays
val intArray = intArrayOf(1,2,3,4)
val arrayOfInts = arrayOf(1,2,3,4)
// boolean and Boolean arrays
val booleanArray = booleanArrayOf(true, false)
val arrayOfBooleans = arrayOf(true, false)
// char and Character arrays
val charArray = charArrayOf('a','b','c')
val arrayOfChars = arrayOf('a', 'b', 'c')
}
使用Intellij的Kotlin字节码反编译器,该代码段反编译为:
public final class PrimitiveArrays {
public static final void main(String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
// long and Long arrays
long[] var10000 = new long[]{1L, 2L, 3L, 4L};
Long[] var9 = new Long[]{1L, 2L, 3L, 4L};
// int and Integer arrays
int[] var10 = new int[]{1, 2, 3, 4};
Integer[] var11 = new Integer[]{1, 2, 3, 4};
// boolean and Boolean arrays
boolean[] var12 = new boolean[]{true, false};
Boolean[] var13 = new Boolean[]{true, false};
// char and Character arrays
char[] var14 = new char[]{'a', 'b', 'c'};
Character[] var15 = new Character[]{'a', 'b', 'c'};
}
}
首先,请注意Kotlin为您的阵列提供了有用的初始化功能。对于原始数组和对象数组。其次,它们是如何编译的。例如,LongArray
变为long[]
和Array
变为Long[]
。
现在,您可以看到这些数组之间的差异。但是,我没有提到您应该利用哪个。您应该像Java一样使用基本类型。这是由于自动装箱和拆箱会对应用程序产生性能影响。
对于较小的工作负载,结果可能微不足道。另一方面,对于性能至关重要的应用中的较大阵列,此可能很小的更改可能会产生明显的影响。有关此主题的更多信息,请参见此处。
如果需要将空值存储在数组中,则仍然需要引用回包装/对象数组。在大多数情况下,我认为您应该能够使用原始数组,但是总会有很多时候无法使用原始数组。话虽这么说,大多数时候我们List
都只使用s,所以所有这些都不重要。
现在,您应该更好地了解原始数组(如)LongArray
和对象数组(如)之间的区别Array
。如果不是,那我让你失败了,对此我表示歉意。