Kotlin中如何声明与Java泛型通配符Map等价的变量或字段
Kotlin中等价Java指定类型的声明方式
直接可用的等价代码
在原有Java定义(Model<T extends Model>、Java侧的lookup变量声明)保持不变的前提下,可直接写出完全兼容、语义无偏差的Kotlin变量/类字段声明:
// 顶层变量写法 val lookup: MutableMap<Class<out Model<*>>, String> = mutableMapOf() // 类字段写法 class DemoRepository { val lookup: MutableMap<Class<out Model<*>>, String> = mutableMapOf() }
逐部分对应逻辑
所有语法转换严格遵循Java和Kotlin的泛型类型映射规则,没有自定义的语义偏移:
- 原Java的
Map<Class<...>, String>是可变Map接口类型,按照Kotlin和Java互操作的默认类型映射规则,直接对应Kotlin的MutableMap。如果换成只读的Map类型,会丢失原Java变量的可修改能力,无法执行put、remove等操作,和原语义不等价 - 原Java的
Class<? extends Model<?>>逐块转换:- Java无界通配
?对应Kotlin的星投影*,因此Model<?>直接写为Model<*>,匹配原Java无边界接收任意泛型参数Model实例的要求 - Java协变边界
? extends Model<...>对应Kotlin的协变投影关键字out,因此带类边界的Class类型写为Class<out Model<*>>,和原Java中“可接收所有Model子类Class对象”的协变兼容能力完全一致
- Java无界通配
- 原Java的
new HashMap<>()对应Kotlin标准库的mutableMapOf()工厂方法,生成的可变Map实例和Java HashMap的行为完全匹配
常见的不等价错误写法
以下写法看起来类似,但和原Java类型存在语义偏差,不属于完全等价的声明:
- 误用Kotlin反射的
KClass替代Java原生Class:KClass属于Kotlin反射体系的类型,和Java标准库的java.lang.Class是完全不同的类型,无法和原Java侧的类型兼容 - 漏掉协变投影关键字
out:如果写为Class<Model<*>>,会收窄原本的协变类型边界,失去接收任意Model子类Class实例的兼容能力 - 误用不可变
Map替代MutableMap:会锁死Map的修改能力,和原Java HashMap的可变语义不匹配
内容的提问来源于stack exchange,提问作者Gelin Luo
相关产品推荐
相关产品推荐

