在Kotlin中实例化通用数组
为什么这不编译? 我得到3行的编译错误
不能使用T作为实体类型参数。 改用类
class Matrix2d<T>(val rows: Int, val cols: Int, init: (Int, Int) -> T) { var data = Array(rows * cols, { i -> val r = Math.floor(i.toDouble() / cols).toInt() init(r, i - r * cols) }) operator fun get(row: Int, col: Int): T = data[row * cols + col] operator fun set(row: Int, col: Int, v: T) = { data[row * cols + col] = v } }
解
我添加了一个工厂函数,看起来像第二个构造函数,但在内联函数中实现
class Matrix2d<T>(val rows: Int, val cols: Int, private val data: Array<T>) { companion object { operator inline fun <reified T> invoke(rows: Int, cols: Int, init: (Int, Int) -> T): Matrix2d<T> { return Matrix2d(rows, cols, Array(rows * cols, { i -> val r = Math.floor(i.toDouble() / cols).toInt() init(r, i - r * cols) })) } } init { if (rows * cols != data.size) throw IllegalArgumentException("Illegal array size: ${data.size}") } operator fun get(row: Int, col: Int): T = data[row * cols + col] operator fun set(row: Int, col: Int, v: T) { data[row * cols + col] = v } }
Kotlin数组映射到的JVM数组需要在编译时知道元素类型来创建数组的实例。
所以你可以实例化Array<String>
或Array<Any>
,而不是Array<T>
,其中T
是一个类型参数,代表在编译时被擦除的类型,因此是未知的。 要指定在编译时必须知道类型参数,将使用reified
修饰符进行标记。
有几种选择,你可以在这种情况下做什么:
-
使用
MutableList<T>
存储元素,不需要实现T:// MutableList function, available in Kotlin 1.1 val data = MutableList(rows * cols, { i -> val r = i / cols init(r, i % cols) }) // or in Kotlin 1.0 val data = mutableListOf<T>().apply { repeat(rows * cols) { i -> val r = i / cols add(init(r, i % cols)) } }
-
使用具体化的类型参数从内联函数创建一个数组:
inline fun <reified T> Matrix2d(val rows: Int, val cols: Int, init: (Int, Int) -> T) = Matrix2d(rows, cols, Array(rows * cols, { .... }) class Matrix2d<T> @PublishedApi internal constructor( val rows: Int, val cols: Int, private val data: Array<T> )
-
使用
Array<Any?>
作为存储,并在get
函数中将其值T
:val data = Array<Any?>(rows * cols, { .... }) operator fun get(row: Int, col: Int): T = data[row * cols + col] as T
-
将
Class<T>
或KClass<T>
类型的参数传递给构造函数,并使用java反射来创建数组的实例。