как назначить java.util.Привязанная карта к kotlin.collections.Map

#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 являются несвязанными интерфейсами 🙁