在Kotlin中将任何数组转换为数组

时间:2017-07-13 16:52:09

标签: kotlin

我通过从Kotlin中的Map<String, Any>加载数据来初始化一个类。由于这张地图直接来自JSON,我不确定任何给定的密钥是否存在,或者它的值是我期望的类型。为了安全地打开这个地图,我做了以下工作,看起来效果很好:

a = rawData["A"] as? String ?: ""

其中一些数据是进一步嵌套的JSON,我将其解包到Arrays;我试图以同样的方式做到这一点:

b = rawData["B"] as? Array<String> ?: arrayOf<String>()

然而,当我尝试使用数组(如上所述)时,IntelliJ大惊小怪,说

  

警告:(111,30)Kotlin:未经检查演员:是吗?到Array&lt; String&gt;

这只是IDE让自己陷入困境,或者这种方法对于Arrays来说真的不安全,尽管对其他类型来说看似非常安全吗?

2 个答案:

答案 0 :(得分:2)

我准备把这称为bug,因为Array是一个具体化的类型,这意味着它的泛型参数实际上可以在运行时检查(例如,与List不同)。我已经尝试过查看它是否已被提交,事实证明编译器实际上是向您显示警告的权利。正如您在对this issue的回复中所看到的那样,这种演员阵容仍然存在可空性问题。

val a = arrayOf("foo", "bar", null) as Array<String>
println(a[2].length)

此示例中的阵列已成功投射(使用as,他们不会使用as?抛出异常,他们不会返回null但是,演员不能确保这是Array<String>,只是它是Array<String?>

这意味着您可以稍后从转换后输入null的变量中读取Array<String>值,而编译器不会再发出警告。

答案 1 :(得分:1)

对于这个问题的任何以后的读者,请使用解决方案扩展接受的答案:

要安全地将Any强制转换为Kotlin中特定类型的数组,您必须首先强制转换为无类型的数组(有关原因,请参阅上面zsmb13的答案),然后将该数组过滤为所需的类型。

例如,要将input: Any转换为String实例的数组,您可以调用:

val inputAsArray = (input as? Array<*>)?.filterIsInstance<String>()