#java #kotlin #collections
Вопрос:
Я объявил метод, который принимает карту в качестве параметра:
fun myKotlinMethod(myParameter:Maplt;String,Stringgt;)...
Позже я прочитал данные из json. Я получаю объект типа: java.util.LinkedHashMaplt;*, *gt;
мне нужно использовать отражение для вызова myKotlinMethod
. Перед этим я проверяю, соответствует ли значение . myParameter
Я спрашиваю тип параметра, используя отражение котлина, и я получаю kotlin.collections.Maplt;*, *gt;
.
суть в том, что java.util.LinkedHashMaplt;*, *gt;
это не реализуется kotlin.collections.Maplt;*, *gt;
(не может) и, следовательно, не может быть назначено.
Я использую этот метод для проверки подлинности
inline fun isAssignable(parameterType: KType, valueType: KType): Boolean { if (parameterType == valueType) return true return parameterType.isSubtypeOf(valueType) }
и я проверяю, как
if (isAssignable(parameter.type.classifier!!.starProjectedType, parameterValue::class.starProjectedType))
Я знаю о какой-то темной магии, которую котлин применяет к коллекции во время компиляции, но во время выполнения следует использовать классы java. Это не мой случай, так как я получаю классы kotlin во время выполнения.
Итак, правильно ли я проверяю совместимость типов коллекций?
Комментарии:
1. Вы хотели
parameterType.isSupertypeOf(valueType)
вместо этого проверить?
Ответ №1:
Вы, кажется, написали это наоборот:
// you can even delete the parameterType == valueType check // isSubtypeOf returns true if the types are the same return parameterType.isSubtypeOf(valueType)
Вызов метода допустим, если тип значения является подтипом типа параметра, поэтому он должен быть:
return valueType.isSubtypeOf(parameterType)
Однако обратите внимание, что это совсем небезопасно. Поскольку вы знаете только , что значение равно a LinkedHashMaplt;*, *gt;
, что делать, если на карте есть Int
s, Double
s или UUID
s? Это все равно пройдет проверку подтипа. Поскольку вы использовали starProjectedType
тип параметра, вы выбросили lt;String, Stringgt;
часть типа и на самом деле не проверили, что значение на самом деле содержит только строки.
Чтобы убедиться в совместимости коллекций, вам также следует проверить элементы коллекции:
fun isAssignableToMapStringString(value: Any) = if (value is Maplt;*, *gt;) { value.all { it.value is String amp;amp; it.key is String } } else { false }
Хотя это может быть довольно трудно обобщить на что-либо KType
. Вам придется много размышлять, чтобы извлечь элементы из коллекции. И вам придется обрабатывать карты и коллекции отдельно, поскольку Map
и Collection
являются несвязанными интерфейсами 🙁