如何在泛型ConverterInterface列表中调用收发泛型对象的方法?
解决泛型转换器列表的类型安全调用问题
这个问题的核心在于你的ConverterInterface<T>是不变泛型接口——它同时包含了消费T的方法(sender需要传入T)和生产T的方法(receiver返回T),这导致你无法用单一的协变(out)或逆变(in)修饰符来兼容所有方法的调用,而通配符*会让编译器无法确定具体的T类型,从而禁止调用需要传入T的sender方法。
下面是几种无需强制类型转换就能安全调用方法的解决方案:
方案1:如果列表中所有转换器都是同一种类型
如果你的列表只存放处理同一类型的转换器,直接明确列表的泛型类型即可:
fun test(){ // 明确列表是处理String类型的转换器集合 val testList: List<ConverterInterface<String>> = listOf(objA) testList[0].receiver(byteArrayOf()) // 正常工作 testList[0].sender("") // 正常工作,编译器知道T是String }
方案2:用具体化泛型函数匹配类型(支持多类型转换器)
通过reified关键字让编译器在运行时获取具体的T类型,然后检查列表中的转换器是否匹配该类型,安全调用sender:
inline fun <reified T> sendToMatchingConverter(converters: List<ConverterInterface<*>>, value: T) { converters.forEach { converter -> // 检查转换器是否处理当前类型T if (converter is ConverterInterface<T>) { converter.sender(value) } } } // 调用示例 fun test(){ val testList: List<ConverterInterface<*>> = listOf(objA) sendToMatchingConverter(testList, "") // 只会匹配String类型的转换器 }
方案3:用密封类封装不同类型的转换器(类型安全的多类型管理)
如果需要存储多种不同类型的转换器,用密封类做类型标记,通过when表达式做类型匹配,完全避免类型转换:
// 密封类封装不同类型的转换器 sealed class ConverterHolder { data class StringConverter(val converter: ConverterInterface<String>) : ConverterHolder() data class IntConverter(val converter: ConverterInterface<Int>) : ConverterHolder() // 可扩展其他类型的转换器封装 } // 使用示例 fun test(){ val testList: List<ConverterHolder> = listOf(ConverterHolder.StringConverter(objA)) testList.forEach { holder -> when(holder) { is ConverterHolder.StringConverter -> holder.converter.sender("hello") is ConverterHolder.IntConverter -> holder.converter.sender(123) } } }
为什么之前的尝试会失败?
List<ConverterInterface<Any>>:泛型默认是不变的,ConverterInterface<String>并非ConverterInterface<Any>的子类,所以无法将objA加入列表。List<ConverterInterface<out Any>>:协变修饰符out只允许调用返回T的方法(如receiver),禁止调用接收T的方法(如sender),因为协变接口只能生产T,不能消费T。List<ConverterInterface<*>>:通配符*代表未知类型,编译器无法确定传入的参数是否符合该类型,所以禁止调用需要传入T的sender方法。
内容的提问来源于stack exchange,提问作者Kent J.
相关产品推荐
相关产品推荐

