java - Kotlin - 无法创建两个具有不同列表类型参数的构造函数

标签 java generics kotlin jvm

我正在尝试创建以下类:

class MyClass {

    var foos: List<Foo> = listOf()

    constructor(foos: List<Foo>) {
        this.foos = foos
    }

    constructor(bars: List<Bar>) : super() {
        this.foos = bars.map { bar ->
            Foo(bar)
        }
    }
}


但是,我收到一条错误消息:

Platform declaration clash: The following declarations have the same JVM signature ( (Ljava/util/List;)V):


我知道它们都是 List 对象,但它们是用泛型类型化的,所以我确信这不会有问题。

最佳答案

你遇到这个问题是因为在 java 中存在一个叫做 type erasure 的东西。 .并且因为 kotlin 使用 JVM,它也受到此限制的影响。给一个 TL;DR;

通用类型保留在 .class 中文件,以便 java 知道该类(在您的情况下为 List )是通用的。但它无法跟踪实例的通用类型。所以实例List<Foo>List<Bar>都在他们的 raw type 中处理运行时的形式(List)。请记住,泛型仅在编译时使用以确保类型安全。

要克服此限制,您可以在 kotlin 中使用运算符重载。我们正在查看的运算符是 ()让你调用任何实例。通过使用 companion object我们甚至可以做到这一点 invoke看起来像一个构造函数,并且像一个构造函数一样被调用(MyClass())。您的代码可能如下所示:

class MyClass(var foos: List<Foo>) {
    companion object {
        operator fun invoke(bars: List<Bar>) = MyClass(bars.map(::Foo))
    }
}

它允许您像这样简单地调用它:

val mc1 = MyClass(foos) // calls constructor
val mc2 = MyClass(bars) // calls companion.invoke

关于java - Kotlin - 无法创建两个具有不同列表类型参数的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56384970/

相关文章:

java - 在 Java 中为具有类型参数的类编写平等契约

generics - F#成员约束+ ^ a byref参数

spring - 为什么 Spring Boot 2.7.x 不使用 kotlin 1.7 或 1.8

java - Kotlin 比 java 更难逆向工程吗

java - 功能依赖分析

java - 如何通过注释正确配置 2 级 hibernate 实体缓存

java - 我在 Java 8 代码的列表中得到的整数值为 'Integer'

java - 运行docker容器 "NoClassDefFoundError"时出错

C++ 返回泛型类型集合的正确方法

android - 加密Room数据库的特定列