Вывод типа компилятора Kotlin не может выбрать способ вызова (двусмысленность с типичными типами)

Итак, у меня есть некоторые методы 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 (разделитель: CharSequence !, vararg array: String!): String! определенный в JavaClass

Я даже не могу назвать аргументы, потому что Kotlin не позволяет аргументировать имена для функций, отличных от Kotlin.

EDIT: заменил параметр типа Generic E на простые ссылки String в заголовках метода Java, и он сработал! Поэтому я предполагаю, что это несовместимость вывода типа с типичными типами или что-то в этом роде?



Я уверен, что это должно быть что-то с оператором распространения (*). Но я не могу передать array параметров varargs в функцию join если я его не использую.

Как я могу решить это, не касаясь кода Java?

ДА, я ЗНАЮ, что существует функция расширения Array.joinToString, но это разрешило бы только этот конкретный случай. Мне нужно знать общее решение.

Я не думаю, что это специально для Котлина. Проблема состоит в том, что общий аргумент E имеет тип CharSequence поэтому ваш вызов становится чем-то вроде join("separator", "word1", "word2") который, действительно, неоднозначен с первого аргумента типа E == CharSequence совпадает с типом других аргументов.

Похоже, вам понадобится создать вспомогательный класс в 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

Вероятно, вы неправильно работаете с типами NULL

Некоторое время я боролся с этой ошибкой, но, наконец, придумал решение. У меня было это сначала

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

Коллекция предметов – MutableSet? поэтому он имеет значение NULL, а коллекции других элементов также имеют значение NULL. Итак, после добавления? перед применением и передачей недействительной коллекции функции removeAll ошибки исчезли.

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