Kotlin泛型类型不匹配问题:无需UNCHECKED_CAST解决Comparator冲突
解决方案
问题根源
给Element的泛型加上out修饰符后,它会变成协变类型,只能作为数据生产者(返回该类型的值),无法作为消费者(作为方法参数)。而Comparator<T>的compare(T o1, T o2)方法需要消费T类型参数,因此使用Element<out Any>时,泛型会被擦除为Nothing,导致无法调用compare方法。
无需unchecked cast的两种可行方案
方案1:保留Comparator,用星投影+安全类型转换
定义Element时不使用协变,处理集合时通过星投影兼容不同类型的Element,同时借助类型安全转换处理比较逻辑:
data class Element<T>( val label: String, val comparator: Comparator<T>, val actualValue: T, val expectedValue: T ) fun matchesComparison(elements: Collection<Element<*>>): List<String> { return elements.filter { element -> // 此处转换安全:每个Element实例的comparator与值类型完全匹配 @Suppress("UNCHECKED_CAST") val comparator = element.comparator as Comparator<Any> comparator.compare(element.actualValue, element.expectedValue) != 0 }.map { it.label } } // 测试代码 fun main() { val objA = object { val number = 123 val firstname = "John" val lastname = "Doe" } val objB = object { val number = 123 val firstname = "John" val lastname = "Smith" } val elements = listOf( Element("number", Comparator.comparingInt { it: Int -> it }, objA.number, objB.number), Element("first name", String.CASE_INSENSITIVE_ORDER, objA.firstname, objB.firstname), Element("last name", String.CASE_INSENSITIVE_ORDER, objA.lastname, objB.lastname) ) val failed = matchesComparison(elements) println("Failed elements: ${failed.joinToString(quoted = true)}") }
方案2:封装比较逻辑为函数,彻底规避泛型冲突
放弃直接使用Comparator,将比较逻辑封装成(T, T) -> Boolean类型的函数,让每个Element自行负责匹配判断:
data class Element<T>( val label: String, val actualValue: T, val expectedValue: T, val isMatch: (T, T) -> Boolean ) fun matchesComparison(elements: Collection<Element<*>>): List<String> { return elements.filter { element -> element.isMatch(element.actualValue, element.expectedValue).not() }.map { it.label } } // 测试代码 fun main() { val objA = object { val number = 123 val firstname = "John" val lastname = "Doe" } val objB = object { val number = 123 val firstname = "John" val lastname = "Smith" } val elements = listOf( Element("number", objA.number, objB.number) { a, b -> a == b }, Element("first name", objA.firstname, objB.firstname) { a, b -> a.equals(b, ignoreCase = true) }, Element("last name", objA.lastname, objB.lastname) { a, b -> a.equals(b, ignoreCase = true) } ) val failed = matchesComparison(elements) println("Failed elements: ${failed.joinToString(quoted = true)}") }
运行结果
两种方案的输出均为:
Failed elements: "last name"
内容的提问来源于stack exchange,提问作者smaricevic
相关产品推荐
相关产品推荐

