Kotlin函数重载问题:varargs与单参数函数调用冲突
Kotlin重载函数触发递归?看这篇就懂了
嘿,这个问题我之前踩过坑!本质是Kotlin的重载解析规则和Java不一样,才导致了你遇到的递归问题。
先拆解下你的代码:
fun isBlank(s: String?) : Boolean { return s.isNullOrBlank() } fun isBlank(vararg strings: String) : Boolean { return strings.isEmpty() || strings.any { isBlank(it) } }
当你在第二个函数里调用isBlank(it)时,it是非空的String类型。在Kotlin中,vararg参数支持直接传入单个元素(编译器会自动把它包装成数组),这时候编译器会优先匹配参数类型更贴合的重载——也就是第二个接受vararg String的函数,于是就触发了递归调用自己,而不是你期望的第一个函数。
反观Java,String和String[]是完全独立的类型,调用isBlank(it)时只会匹配单个String参数的重载,自然不会有混淆。
几种快速修复方案
1. 给编译器“指路”,明确调用可空版本
你可以把it显式转成可空的String?,让编译器知道要调用第一个函数:
fun isBlank(vararg strings: String) : Boolean { return strings.isEmpty() || strings.any { isBlank(it as String?) } }
2. 直接用Kotlin标准库,省得自己封装
其实你的第一个函数就是对isNullOrBlank()的简单封装,完全可以直接在第二个函数里用标准库方法,彻底避免重载冲突:
fun isBlank(vararg strings: String) : Boolean { return strings.isEmpty() || strings.any { it.isNullOrBlank() } } // 要是第一个函数没用了,直接删掉也没问题
3. 干脆重命名,避免同名重载
最省心的方式就是给其中一个函数改个名字,比如把单个字符串检查的函数改成isStringBlank:
fun isStringBlank(s: String?) : Boolean { return s.isNullOrBlank() } fun isBlank(vararg strings: String) : Boolean { return strings.isEmpty() || strings.any { isStringBlank(it) } }
4. 加@JvmName注解(兼顾Java调用)
如果你的代码需要给Java调用,又想保留Kotlin里的同名重载,可以给第一个函数加@JvmName注解,让JVM层面的方法名不同,同时在Kotlin里明确指定调用:
@JvmName("isBlankNullable") fun isBlank(s: String?) : Boolean { return s.isNullOrBlank() } fun isBlank(vararg strings: String) : Boolean { return strings.isEmpty() || strings.any { this::isBlank.call(it) } }
这样就能完美解决递归问题啦~
内容的提问来源于stack exchange,提问作者nllsdfx
相关产品推荐
相关产品推荐

