我通过从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来说真的不安全,尽管对其他类型来说看似非常安全吗?
答案 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>()