如何为ArrayList实现类型安全的getTypeOrNull泛型扩展函数?
正确实现ArrayList按索引获取指定类型元素或返回null的扩展函数
你写的代码存在两个核心问题:
- 泛型擦除导致类型检查失效:JVM在运行时会擦除泛型类型信息,
item is T这种写法编译器直接会报错,因为它无法在运行时确认T的具体类型。 - 泛型声明逻辑有误:原函数的
<T : E>约束写法不合理,接收者是ArrayList<E>,但泛型参数的声明顺序和约束逻辑不符合Kotlin的语法规范。
下面提供两种可靠的实现方式:
方式一:使用reified泛型(推荐,更简洁)
借助inline函数配合reified关键字,可以在运行时保留泛型类型信息,实现安全的类型转换:
inline fun <reified T> ArrayList<*>.getTypeOrNull(index: Int): T? { return getOrNull(index) as? T }
使用示例:
val list: ArrayList<Any> = arrayListOf("Hello", 123, true) val str: String? = list.getTypeOrNull(0) // 返回"Hello" val num: Int? = list.getTypeOrNull(1) // 返回123 val bool: Boolean? = list.getTypeOrNull(2) // 返回true val invalid: Double? = list.getTypeOrNull(3) // 返回null
方式二:传递Class类型参数(兼容非inline场景)
如果不能使用inline函数(比如某些性能敏感或特殊需求场景),可以通过显式传递Class<T>对象来实现类型检查:
fun <T> ArrayList<*>.getTypeOrNull(index: Int, clazz: Class<T>): T? { val item = getOrNull(index) return if (clazz.isInstance(item)) { clazz.cast(item) } else { null } }
使用示例:
val list: ArrayList<Any> = arrayListOf("Hello", 123, true) val str: String? = list.getTypeOrNull(0, String::class.java) val num: Int? = list.getTypeOrNull(1, Int::class.java)
两种方式都能实现你想要的:按索引获取元素,若元素是指定类型则返回,否则返回null。
内容的提问来源于stack exchange,提问作者Антон
相关产品推荐
相关产品推荐

