Smart Cast не работает должным образом

У меня есть следующий код Kotlin:

fun handleResult(clazz: Any){
    val store = App.getBoxStore();
    if(clazz is List<*> && clazz.size > 0){
        val items: List<*> = clazz;
        val item = items.get(0);
        val box = store.boxFor(item!!::class.java)
        box.put(items)
    }
}

Он берет объект, проверяет, является ли он коллекцией, и если это так, берет элемент для проверки класса элементов коллекции, создает Box из библиотеки с именем ObjectBox, которая является базой данных, и они помещают список элементов в база данных.

Тем не менее, я получаю следующее сообщение об ошибке в поле Box.put:

Error:(45, 17) None of the following functions can be called with the 
arguments supplied:
public open fun put(@Nullable vararg p0: Nothing!): Unit defined in 
io.objectbox.Box
public open fun put(@Nullable p0: (Nothing..Collection<Nothing!>?)): 
Unit defined in io.objectbox.Box
public open fun put(p0: Nothing!): Long defined in io.objectbox.Box

Подпись метода, который я хочу использовать:

 public void put(@Nullable Collection<T> entities)

Он возвращает коллекцию универсального типа, поскольку список является коллекцией, он должен работать.

Я также явно преобразовал его в список, но он все еще говорит то же самое.

Спасибо!

1 ответ

Решение

Проблема в том, что обобщенному объявлению Collection нужен фактический тип. Однако вы используете List<*>, который не имеет указанного типа, и компилятор предполагает, что универсальный тип, связанный с Box, равен "Nothing".

Есть несколько способов это исправить.

  • Если вы знаете конкретный набор типов, для которых он будет использоваться заранее, вы можете использовать инструкцию when для правильного умного приведения типа List, и тогда вы сможете создать правильный экземпляр Box, вызывающего Метод put() без проблем.

    if(clazz is List<*> && clazz.size > 0){
        val items = clazz
        val item = items.get(0)
        when (item) {
            is Int -> {
                val box = store.boxFor(Int::class.java)
                box.put(items.filterIsInstance<Int>())
            }
            is ...
        }
    
    }
    
  • Используйте рефлексию, чтобы получить метод put() из Box, а затем вызовите его. Это обойдёт семантические проверки компилятора, но это немного более сомнительно и может столкнуться с проблемами позже.

    if(clazz is List<*> && clazz.size > 0){
        val items = clazz
        val item = items.get(0)
        val box = store.boxFor(Int::class.java)
        val putMethod = box::class.java.getDeclaredMethod("put", item!!::class.java)
        putMethod.invoke(box, items)
    }
    
Другие вопросы по тегам