Kotlin Список против java .util.List generi c тип внутри Java код - PullRequest
0 голосов
/ 16 апреля 2020

Я застрял со странным поведением при переносе моего проекта на kotlin.

Это произошло, когда я пытался сгенерировать инжекторы кинжала. Проблема в java или кинжале, кто-то не может решить kotlin Список из generi c type

Пример:


interface CacheEntity<Result> {
  fun onResult(result: Result)
  fun getUpdatableData(): Observable<Result>
}
class CacheRepository< Result, Entity:CacheEntity<Result> >(
  val entity: Entity) {

   // do some operations with Entity
   fun doSome() {
     entity.getUpdatableData()
     entity.onResult(...)
   }
}
class UserRepository: CacheEntity<User> {
  override fun onResult(result: User) {}
  override fun getUpdatableData(): Observable<User> {}
}

Теперь, если я Пытаюсь создать кешированный экземпляр репозитория пользователя, все в порядке. Затем этот код преобразуется в приложение с помощью инъекций кинжала

val cachedUserRepo = CacheRepository<User, UserRepository>(UserRepository())

Но! Если я пытаюсь привести список данных

class OrdersRepository: CacheEntity<List<Order>> {
  // overrides CacheEntity methods
}

val cachedOrdersRepo = CacheRepository<List<Order>, OrdersRepository>(OrdersRepository())

Все хорошо, но не в сгенерированном кинжалом java коде: MyComponent. java


private CacheRepository<List<Order>, OrdersRepository> cachedOrdersRepository;

ошибка при построении

error: type argument OrdersRepository is not within bounds of type-variable Entity
  private Provider<CachedRepository<List<Order>, OrdersRepository>> cachedOrdersRepository;
                                                              ^
  where Entity,Result are type-variables:
    Entity extends CacheEntity<Result> declared in class CacheRepository
    Result extends Object declared in class CacheRepository

Java код содержит java .util.List , который несовместим с kotlin .collections.List , но класс модуля кинжала записан в kotlin и возвращает действительный kotlin kotlin .collections.List

@Module
object RepoModule {
  @JvmStatic
  @Provides
  fun provideCacheOrdersRepository(): CacheRepository<List<Order>, OrdersRepository> {
    return CacheRepository(OrdersRepository())
  }

}

Итак, как решить эту проблему? У меня есть пара идей, но мне это не нравится:

  • Переписать модуль кинжала в java, он работал до того, как я преобразовал в kotlin

  • Принудительное использование java .util.List , но это очень плохая идея

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Это связано с преобразованием байт-кода списка Kotlin и подстановочных знаков, добавленных в подпись, что делает его java.util.List<? extends T> вместо java.lang.List<T>.

. Чтобы исправить это, не переключаясь на тип инварианта (например, MutableList), вы должны использовать @JvmSuppressWildcards для типа List:

например,

class OrdersRepository: CacheEntity<List<@JvmSuppressWildcards Order>>

Я добавил только один фрагмент вашего полного кода, вы должны проверить список использования и использовать @JvmSuppressWildcards на них.

0 голосов
/ 16 апреля 2020

Хорошо, я нашел быстрое решение: использование MutableList<T> решает эту проблему, и оно кажется совместимым с java.util.List<T> по неизвестной причине.

...