Kotlin 的原始数组和对象数组之间的区别

本文探讨了Kotlin中的原始数组和对象数组之间的差异。与Java类似,Kotlin不允许直接创建原始类型的泛型数组,而是使用特定类如IntArray。这些类在编译时会转换为对应的原始JVM数组。尽管自动装箱和拆箱使得基本类型和包装器类型在某些情况下可以互换,但在数组中,这种转换会导致性能影响。因此,理解何时使用原始数组和对象数组对于性能敏感的应用至关重要。
摘要由CSDN通过智能技术生成

我最初开始写这篇文章是因为我尝试了一些反射代码,并认为我发现了一些有趣的东西。可惜,事实并非如此。相反,它只是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<Long>(3)
// or
val array: Array<Long> = arrayOf(1,2,3)

您可以看到的事实数组使用泛型应强调它不是原始数组。 在Java和Kotlin中,这都是事实,即泛型类型不能是基元。 否则,可以将其切换为数组<long>,我们都会很高兴。 上面的代码编译成一个对象数组长[]代替原始长[]。

这种情况在阵列上是很独特的。 科特林长本身使用可以编译为长要么长在JVM字节码中。 编译的类型取决于字段的可为空性。 数组更明确,因此编译时它们的类型不会改变。

为了避免这种情况,Kotlin提供了一些选择,这些类在向下编译为JVM字节码时变为原始数组。

这些类包括:

KotlinJava
ByteArraybyte[]
CharArraychar[]
ShortArrayshort[]
IntArrayint[]
LongArraylong[]
DoubleArraydouble[]
FloatArrayfloat[]
BooleanArrayboolean[]

这些类也可以在Kotlin和Java之间互换,而无需付出任何额外的努力。

作为最后一个证据,向您展示Kotlin中原始数组与包装式/对象数组之间的区别,我想向您展示一些Kotlin代码,这些代码已转换为Java对应的代码:

@file:JvmName("PrimitiveArrays")
package dev.lankydan

fun main(args: Array<String>) {
  // long and Long arrays
  val longArray = longArrayOf(1,2,3,4)
  val arrayOfLongs = arrayOf<Long>(1,2,3,4)
  // int and Integer arrays
  val intArray = intArrayOf(1,2,3,4)
  val arrayOfInts = arrayOf<Int>(1,2,3,4)
  // boolean and Boolean arrays
  val booleanArray = booleanArrayOf(true, false)
  val arrayOfBooleans = arrayOf<Boolean>(true, false)
  // char and Character arrays
  val charArray = charArrayOf('a','b','c')
  val arrayOfChars = arrayOf<Char>('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>变为Long[]

现在,您可以看到这些数组之间的差异。但是,我没有提到您应该利用哪个。您应该像Java一样使用基本类型。这是由于自动装箱和拆箱会对应用程序产生性能影响。

对于较小的工作负载,结果可能微不足道。另一方面,对于性能至关重要的应用中的较大阵列,此可能很小的更改可能会产生明显的影响。有关此主题的更多信息,请参见此处

如果需要将空值存储在数组中,则仍然需要引用回包装/对象数组。在大多数情况下,我认为您应该能够使用原始数组,但是总会有很多时候无法使用原始数组。话虽这么说,大多数时候我们List都只使用s,所以所有这些都不重要。

现在,您应该更好地了解原始数组(如)LongArray和对象数组(如)之间的区别Array<Long>。如果不是,那我让你失败了,对此我表示歉意。

from: https://dev.to//lankydandev/kotlin-primitive-and-object-arrays-4dp0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值