【问题标题】:Define array Type in Kotlin在 Kotlin 中定义数组类型
【发布时间】:2021-03-20 08:55:14
【问题描述】:

我已经初始化了这样的字符串数组

var capitals = arrayOf("Tokyo","Moscow","Paris","Washington","Beijing")

但我没有将它的类型指定为 String。我想当我在元素之后使用 arrayOf 构造函数时,我应该指定类型。

尝试下面的代码会给我错误属性 gettter 和 setter 预期

为什么我不能在<> 括号内指定类型?

var capitals = arrayOf("Tokyo","Moscow","Paris","Washington","Beijing"):Array<String>

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    你必须在变量声明之后指定类型,而不是在初始化之后:

    var capitals: Array<String> = arrayOf("Tokyo", "Moscow", "Paris", "Washington", "Beijing")
    

    或者你可以显式设置arrayOf的类型参数:

    var capitals = arrayOf<String>("Tokyo", "Moscow", "Paris", "Washington", "Beijing")
    

    【讨论】:

      【解决方案2】:

      我想当我在元素之后使用 arrayOf 构造函数时,我应该指定类型。

      编译器需要知道每个值的类型——但它通常可以infer 它已经知道的类型。所以通常¹省略类型。

      在这种情况下,编译器知道每个元素都是String,因此列表类型只能是String(或其超类型之一:String?CharSequenceCharSequence?、@987654333 @、Comparable&lt;String&gt;?AnyAny?)。所以它推断出最严格的有效类型:List&lt;String&gt;

      当然,您可以根据需要手动指定类型。 (例如,您可能希望稍后能够在数组中设置空值或其他非字符串值。)  实际上,在这种情况下,您可以通过两种方式来做到这一点。你可以为arrayOf()指定类型参数:

      var capitals = arrayOf<Any?>("Tokyo", "Moscow", "Paris", "Washington", "Beijing")
      

      或者您可以指定要分配给它的变量的类型²:

      var capitals: Array<Any?> = arrayOf("Tokyo", "Moscow", "Paris", "Washington", "Beijing")
      

      两者在这里具有相同的效果,尽管第一个可能更好。 (它更短,这总是好的!  而且,它可以扩展到更复杂的表达式。)


      1:在某些情况下,明确指定类型是一种很好的做法,即使您不需要。例如:

      • 您可能想故意放宽类型,如上所示。

      • 您可能有一个从 Java 函数返回的值,编译器无法判断它是否应该为空(platform type)。如果您碰巧知道这一点,您可以相应地指定可空或不可空类型。

      • 您可能有一个作为公共 API 一部分的函数,并且您不希望冒着由于某些内部更改而间接更改其类型的风险。 (当然,这只是用expression body 定义的函数的问题;你总是必须为block body 指定一个类型,除非它返回Unit。)


      2:第二个例子表明编译器在推断类型时使用了周围的上下文。如果它在推断arrayOf() 的类型参数时查看String 参数,那么这将给出Array&lt;String&gt; — 不能将其分配给Array&lt;Any?&gt; 变量,因为Array 不是covariant

      但是,正如language spec 所说:

      表达式的类型不仅可以从它们的参数导出,还可以从它们的用法导出。

      【讨论】:

        【解决方案3】:

        您也可以as 关键字来指定您的类型:

        var capitals = arrayOf("Tokyo", "Moscow", "Paris", "Washington", "Beijing") as Array<String>
        

        【讨论】:

        • 这仅在此处有效,因为您正在转换为相同的类型。如果您转换为不同的类型,您将收到运行时错误(立即的ClassCastException 或稍后的ArrayStoreException)。 (另外,还有一个无关的:。)
        • 就是这样!如果你想使用不同的类型,你应该尝试as Array&lt;Any&gt; 这适用于所有 kotlin 类型
        • 不,这将无法正常工作。 as 是一个强制转换,一个强制转换不会将值转换 为所需的类型——它向编译器保证它已经 正确的类型。在这种情况下,它不是! Array 在 Kotlin 中不是协变的(与 Java 不同),因此 Array&lt;Any&gt;Array&lt;String&gt; 是不兼容的类型。强制转换会产生运行时错误,或者之后尝试使用数组可能会这样做。
        • 我在第一条评论中的意思是as Array&lt;String&gt;arrayOf&lt;String&gt; 可以给你相同的结果即使他们有不同的Exception 对吗?
        猜你喜欢
        • 1970-01-01
        • 2018-04-04
        • 2010-12-29
        • 2019-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-09
        • 2019-08-21
        相关资源
        最近更新 更多