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) }