我试过了,代码没有编译。
class GenericClass<T>() {
private var arr : Array<T>? = null
{
arr = Array<T>(10, { null })
}
}
答案 0 :(得分:17)
此代码中报告了两个编译器错误:一个是关于可空类型,另一个是关于泛型。
Nullable types 。 Kotlin强制执行可空引用的规则,并且因为T可以实例化,例如,String make arr是Array类型,编译器不允许将空值放入此数组中。如果需要空值,则必须将类型更改为Array:
class GenericClass<T>() {
private var arr : Array<T?>? = null
{
arr = Array(10, { null }) // No need to specify type arguments again
}
}
<强>泛型即可。上面的示例仍然存在编译时错误,因为我们正在尝试构造一个未知类型为T的数组。请注意,Java中也存在此问题。 Kotlin被编译为JVM字节代码需要两件事:
这意味着在字节代码中,Kotlin必须创建一个具体类型的数组,而不是未知类型T.它可以在看到Array时创建对象数组,但这不起作用,例如,在此情况下:
fun test() {
fun foo(srts: Array<String?>) {
// ...
}
val gc = GenericClass<String>()
foo(gc.arr)
}
这里,在最后一行,我们试图传递Object [],其中String []是预期的,并获得运行时错误。
这就是为什么Kotlin拒绝创建T的数组。你可以通过明确地抑制类型系统来解决这个问题,即使用类型转换:
class GenericClass<T>() {
val arr : Array<T?>
{
arr = Array<Any?>(10, { null }) as Array<T?>
}
}
这里我们显式请求创建Any数组(编译为Object []),然后将其类型转换为T数组。编译器发出警告,但遵守我们的意愿。
请注意,上面有问题的示例仍然存在,即如果您传递以预期字符串数组的方式创建的数组,则会在运行时失败。
答案 1 :(得分:2)
方法
func handlerMethod() {
//handle your action here after ok is pressed for e.g if you wanna just dismiss the alert then write
dismissViewControllerAnimated(true, completion: nil)
}
来自docs
val array : Array<T?> = kotlin.arrayOfNulls<T>(size)
答案 2 :(得分:1)
如果需要在构造函数中初始化数组,则可以添加内联工厂方法并使用reified T
对其进行参数化。该解决方案的灵感来自答案https://stackoverflow.com/a/41946516/13044086
class GenericClass<T> protected constructor(
private val arr : Array<T?>
) {
companion object {
inline fun <reified T>create(size: Int) = GenericClass<T>(arrayOfNulls(size))
}
}
fun main() {
val strs = GenericClass.create<String>(10)
...
}
请注意,构造函数受到保护,因为内联函数无法访问私有构造函数。
如果在创建对象之后需要创建数组,则可以将创建数组的lambda传递给方法。 Lambda可以在扩展函数内部创建,因此可以保留有关数组类型的信息。 @PublishedApi
批注用于封装私有方法fill
。
import GenericClass.Companion.fill
class GenericClass<T> {
private var arr : Array<T?>? = null
fun show() {
print(arr?.contentToString())
}
private fun fill(arrayFactory: (size: Int) -> Array<T?>) {
this.arr = arrayFactory(10)
}
@PublishedApi
internal fun `access$fill`(arrayFactory: (size: Int) -> Array<T?>) = fill(arrayFactory)
companion object {
inline fun <reified T>GenericClass<T>.fill() {
`access$fill`(arrayFactory = { size -> arrayOfNulls(size) })
}
}
}
fun main() {
val strs = GenericClass<String>()
strs.fill()
strs.show()
}
答案 3 :(得分:0)
您可以使用以下帮助功能:
@Suppress("UNCHECKED_CAST")
fun <T> genericArrayOfNulls(size: Int): Array<T?> {
return arrayOfNulls<Any?>(size) as Array<T?>
}