首页 文章

Kotlin编译器's type inference can' t选择调用哪种方法(泛型类型不明确)

提问于
浏览
3

所以,我有一些带有这些签名的Java方法(为简单起见,删除了注释和代码体):

public class JavaClass {
  public static <E extends CharSequence> E join(E... array) { ... }
  public static <E extends CharSequence> E join(CharSequence separator, E... array) { ... }
}

我在Kotlin中有一些代码,它们调用'join'方法:

class KtClass {
    fun test(vararg array: String) {
        JavaClass.join(*array)
    }
}

到现在为止还挺好;它将传播varargs并调用前方法签名 . 好的!

例如,如果我想使用'separator'参数调用后一种方法签名,则会出现问题:

class KtClass {
    fun test(vararg array: String) {
        JavaClass.join("<br>", *array)
    }
}

此代码将无法编译 . 编译器无法决定调用哪种方法 . 错误:

错误:(5,13)Kotlin:如果没有完成类型推断,不能在以下候选者中进行选择:public open fun join(vararg array:String!):String!在JavaClass public open fun join中定义(separator:CharSequence!,vararg array:String!):String!在JavaClass中定义

我甚至无法命名参数,因为Kotlin不会让非Kotlin函数的参数命名 .

EDIT: 用Java方法头中的普通字符串引用替换了E泛型类型参数,它工作正常!所以我猜这是类型推断与泛型类型或类似东西的不兼容性?



我很确定这必须是 spread operator (*) . 但如果我不使用它,我无法将varargs参数 array 传递给 join 函数 .

如何在不触及Java代码的情况下解决这个问题?

是的,我知道有Array.joinToString扩展函数,但这只能解决这个特殊情况 . 我需要知道一个通用的解决方案 .

3 回答

  • 2

    我不是特定于Kotlin的 . 问题是泛型参数 E 的类型是 CharSequence 所以你的调用变成类似 join("separator", "word1", "word2") 的东西,实际上是不明确的,因为第一个参数类型 E == CharSequence 与其他args的类型相同 .

  • 1

    看起来您需要在Java中创建一个辅助类来桥接互操作问题 . 例如 . :

    public class JavaClassInterop {
        public static <E extends CharSequence> E joinSeparatedBy(CharSequence separator,
                                                                 E... array) {
            return JavaClass.join(separator, array);
        }
    }
    

    然后你可以同时打电话:

    import JavaClass.join
    import JavaClassInterop.joinSeparatedBy
    
    fun main(args: Array<String>) {
        join(*args)
        joinSeparatedBy("<br>", *args)
    }
    
  • 1

    tldr

    Probably you work incorrectly with nullable types

    我在这个错误中挣扎了一段时间,但终于想出了一个解决方案 . 我起初有这个

    user.items.apply {
            removeAll(otherItems)
            removeAll(otherItems2)
        }
    

    items集合是MutableSet?所以它可以为空,其他Items集合也可以为空 . 添加后呢?在apply之前,将非可空集合传递给removeAll函数,错误消失了 .

    user.items?.apply {
            removeAll(otherItems.orEmpty())
            removeAll(otherItems2.orEmpty())
        }
    

相关问题