Kotlin传数组给函数式接口报类型不匹配异常的原因及解决方法
异常产生原因
你遇到的是编译期类型不匹配错误,并非运行时抛出的异常,核心原因有两点:
- Kotlin对声明了
vararg参数的函数式接口做SAM转换时,lambda接收的参数类型固定为Array<out T>,不是Array<T>。你显式将lambda参数标注为Array<String>,和编译器期望的Array<out String>(T为String时的期望类型)类型不兼容,直接触发报错。 - 这个
out投影是Kotlin刻意做的安全约束:Array<out T>表示数组只能作为T的生产者,仅允许读取元素,禁止写入修改,避免函数内部篡改调用方传入的原始数组,引发类型安全问题。你代码中尝试修改ss[0]的逻辑本身就违反了该约束,即便绕过类型匹配检查,也会被编译器拦截写入操作。
解决方法
根据业务需求二选一即可:
方案1:仅读取参数,无需修改内容
直接删除lambda参数的显式类型标注,或显式标注为Array<out String>,不要尝试修改传入的数组元素:
fun main() { val changeFirstElement = VarargsFunction<String> { ss -> // 仅可读取ss元素,不可修改 ss } } fun interface VarargsFunction<T> { fun apply(vararg t: T): Array<out T>? }
方案2:需要修改元素后返回结果
不要直接修改传入的vararg只读数组(也不推荐修改调用方传入的原始参数),先将传入的数组拷贝为可写的普通数组,修改完成后再返回:
fun main() { val changeFirstElement = VarargsFunction<String> { ss -> // 拷贝生成独立的可修改数组,不会影响原始传入参数 val mutableArray = ss.copyOf() if (mutableArray.isNotEmpty()) { mutableArray[0] = "${mutableArray[0]} world" } mutableArray } // 功能测试 val result = changeFirstElement.apply("hello") println(result?.contentToString()) // 控制台输出:[hello world] } fun interface VarargsFunction<T> { fun apply(vararg t: T): Array<out T>? }
注意:禁止通过强制类型转换把
Array<out String>转为Array<String>后直接修改,该写法绕过了编译器的型变检查,当调用方通过展开运算符传入不可变数组实例时,会触发运行时异常。
内容的提问来源于stack exchange,提问作者Molly Tian
相关产品推荐
相关产品推荐

