在Kotlin中,泛型(generic参数)默认是类型擦除(type erasure)的:在运行时没有类型信息。这使得反射、类型转换和读取类型注解变得复杂。对于大多数任务,这是可接受的——常规泛型的工作方式类似于Java。
内联函数使用reified参数可以 "强制" 编译器在调用处 "插入" 具体类型,因此函数可以在运行时对类型执行操作(例如,进行检查,通过反射创建新实例等)。但是,reified只能应用于inline函数中的参数。
比较示例:
// 普通泛型 fun <T> printType(t: T) { println(t.javaClass) // 对List<Int>等将引发ClassCastException } // 使用reified inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // 输出: Int printType("hello") // 输出: String }
应用实践: 通常用于类型检查、类型转换、反射、创建实例,在其他情况下无法获取类型。
"重ified类型的函数可以不是内联的吗?"
reified仅在内联函数中工作。否则不可能在编译时插入类型。不正确的使用示例:
fun <reified T> failFunction() {} // 编译错误:reified类型参数只能用于内联函数
正确的:
inline fun <reified T> goodFunction() {}
故事
在项目中需要通过带有泛型参数的函数通用地解析JSON字符串到任何类型。通过
fun <T> parse(json: String): T的标准实现由于类型擦除不正确工作——无法提取Class<T>来解析集合和泛型模型。通过使用带重ified类型的内联,问题消失了。
故事
一位开发者尝试使用普通构造函数
T()创建类型T的实例,而不使用内联和重ified。在编译时出现错误,因为类型信息已被擦除。通过重写为inline fun <reified T: Any>成功用语言的标准工具解决了所有问题。
故事
尝试在普通函数(没有内联)中使用重ified时——IDE给出了令人困惑的编译错误。开发者花了很长时间寻找原因,直到研究了文档并修复了函数,添加了内联。