我有一个接受Array<String?>
:
fun doStuff(words: Array<String?>) {
// ...
}
有没有办法可以将Array<String>
传递给此功能?按原样,编译器给我一个&#34;类型不匹配&#34;错误。
private val SOME_WORDS = arrayOf("I", "want", "to", "use", "these")
doStuff(SOME_WORDS) // throws a type-mismatch error
我希望尽可能避免SOME_WORDS
成为arrayOf<String?>(...)
。
答案 0 :(得分:4)
使用out
-projected Array<out String?>
:
fun doStuff(words: Array<out String?>) { /* ... */ }
Arrays in Kotlin are invariant,表示Array<A>
和Array<B>
不是任何不同A
和B
的子类型,包括String
和String?
,并且不能将它们作为参数分配和传递来代替彼此。
使用out
- 投影Array<out String?>
使该函数不仅接受Array<String?>
,还接受String?
子类型的数组。基本上,因为类型是final
,所以只有一个这样的子类型,它是String
(非空的,没有?
)。
图片来自:A Whirlwind Tour of the Kotlin Type Hierarchy)
因此,该函数也将接受Arrray<String>
。但是你将无法将可空值放入数组中(这就是投影的工作原理),因此保留了类型安全性(和null安全性)。
答案 1 :(得分:4)
这里的问题是差异。 String
是其可以为空的朋友String?
的子类型,但在Kotlin中,这并不意味着Array<String>
是Array<String?>
的子类型,因为数组不变 。
(在Java中不是这种情况,默认情况下数组是协变的)
如果你有一个像你这样的函数,它需要Array<String?>
类型的参数,你只能传递Array<String?>
,因此Array<String>
是不可能的!如果要启用方法来处理这些数组,请执行以下操作:
fun doStuff(words: Array<out String?>) {
// ...
}
这样就可以传递数组words
协变和Array<String?>
的子类型。
请注意,只有像get()
这样的函数才能访问此类“out -jected”数组。参数words
被称为String?
的制作人。
如果您想了解更多相关信息,请查看官方docs:)
答案 2 :(得分:1)
您应该使用out type projection,因为通用类型Array<String>
在Kotlin中扩展Any
而不是Array<String?>
,例如:
// v--- use out type projection here
fun doStuff(words: Array<out String?>) {
// ...
}
使用时,Kotlin中的out type projection与Java中的upper bounded wildcard ? extends T
类似。并且String
是Kotlin中String?
的子集,因此{K}在{1}}扩展Array<String>
。如您所见,继承图的左侧是upper bounded wildcard继承。