首页 > 解决方案 > Kotlin 类型擦除 - 为什么仅在泛型类型上不同的函数可编译,而仅在返回类型上不同的函数不是?

问题描述

在研究Kotlin 中擦除如何工作的答案时?我发现了一些我还不理解的东西,也没有找到任何来源为什么会这样。

为什么以下无法编译?

fun bar(foo: List<*>) = ""
fun bar(foo: List<*>) = 2

而以下是?

fun bar(foo: List<String>) = ""
fun bar(foo: List<Int>) = 2

对我来说,当添加一个甚至没有使用的泛型类型时,它甚至变得更加好奇,即以下编译:

fun bar(foo: List<*>) = ""
fun <T> bar(foo: List<*>) = 2 // T isn't even used

由于最后一个甚至没有使用T,而且我们知道,泛型在运行时被删除,为什么这个工作,而没有泛型类型的变体没有?

在字节码中,只允许返回类型不同的方法(已经在上面链接的答案中描述)。

欢迎任何提示、来源和/或参考。

现在也在讨论.kotlinlang.org添加了这个问题。

标签: kotlintype-erasure

解决方案


这些函数编译或不编译的原因与 Kotlin 的重载解析规则有关。Kotlin 不使用预期的类型来解决重载,所以当你调用这个函数时:

 val x = bar(listOf(""))

... Kotlin 编译器无法确定类型,并且不允许您通过x显式指定类型来消除调用歧义。

在第二种情况下,不存在重载解决问题,因为函数具有不同的参数类型,并且不存在 JVM 名称冲突问题,因为函数具有不同的返回类型(因此不同的擦除签名)。因此,代码编译。


推荐阅读