簡體   English   中英

Kotlin編譯器的類型推斷無法選擇調用哪種方法(泛型類型的歧義)

[英]Kotlin compiler's type inference can't choose which method to call (ambiguity with generic types)

所以,我有一些帶有這些簽名的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函數的參數命名。

編輯:用Java方法頭中的普通字符串引用替換了E泛型類型參數,它工作正常! 所以我猜這是類型推斷與泛型類型或類似東西的不兼容性?



我很確定這必須是擴展運算符 (*)。 但是如果我不使用它,我無法將varargs參數array傳遞給join函數。

如何在不觸及Java代碼的情況下解決這個問題?

是的,我知道有Array.joinToString擴展函數,但這只能解決這個特殊情況。 我需要知道一個通​​用的解決方案。

我不認為這是特定的Kotlin。 問題是泛型參數E的類型是CharSequence所以你的調用變成了join("separator", "word1", "word2") ,它實際上是第一個參數的模糊,類型為E == CharSequence與其他args的類型相同。

看起來您需要在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)
}

tldr

可能你錯誤​​地使用可空類型

我在這個錯誤中掙扎了一段時間,但終於想出了一個解決方案。 我起初有這個

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

物品集合是一個MutableSet? 所以它可以為空,而其他Items集合也可以為空。 添加后呢? 在apply之前,將非可空集合傳遞給removeAll函數,錯誤消失了。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM