Kotlin List 与 java.util.List 代码中的 java.util.List 泛型类型
Kotlin List vs java.util.List generic type inside Java code
我在将我的项目迁移到 kotlin 时遇到了奇怪的行为。
这是在我尝试生成匕首注射器时发生的。 java 或 dagger 中的问题,有人无法从泛型
中解析 kotlin List
示例:
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())
一切都很好,但在 dagger 生成的 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 不兼容,
但是匕首模块 class 用 kotlin 编写并且 returns 有效的 kotlin kotlin.collections.List
@Module
object RepoModule {
@JvmStatic
@Provides
fun provideCacheOrdersRepository(): CacheRepository<List<Order>, OrdersRepository> {
return CacheRepository(OrdersRepository())
}
}
那么,如何解决这个问题呢?我有几个想法,但我不喜欢这样:
重写 java 中的 dagger 模块,它在我转换为 kotlin
之前有效
强制使用java.util.List,但这是一个非常糟糕的主意
好的,我找到了快速解决方案:使用 MutableList<T>
解决了这个问题,并且由于未知原因它与 java.util.List<T>
接缝兼容。
这与Kotlin列表的字节码转换和签名中添加的通配符有关,使其成为java.util.List<? extends T>
而不是java.lang.List<T>
。
要在不切换到不变类型(例如 MutableList
)的情况下修复它,您应该在 List
类型上使用 @JvmSuppressWildcards
:
例如
class OrdersRepository: CacheEntity<List<@JvmSuppressWildcards Order>>
我只添加了你完整代码的一个片段,你应该检查你的列表用法并在它们上使用 @JvmSuppressWildcards
。
我在将我的项目迁移到 kotlin 时遇到了奇怪的行为。
这是在我尝试生成匕首注射器时发生的。 java 或 dagger 中的问题,有人无法从泛型
中解析 kotlin List示例:
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())
一切都很好,但在 dagger 生成的 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 不兼容, 但是匕首模块 class 用 kotlin 编写并且 returns 有效的 kotlin kotlin.collections.List
@Module
object RepoModule {
@JvmStatic
@Provides
fun provideCacheOrdersRepository(): CacheRepository<List<Order>, OrdersRepository> {
return CacheRepository(OrdersRepository())
}
}
那么,如何解决这个问题呢?我有几个想法,但我不喜欢这样:
重写 java 中的 dagger 模块,它在我转换为 kotlin
之前有效
强制使用java.util.List,但这是一个非常糟糕的主意
好的,我找到了快速解决方案:使用 MutableList<T>
解决了这个问题,并且由于未知原因它与 java.util.List<T>
接缝兼容。
这与Kotlin列表的字节码转换和签名中添加的通配符有关,使其成为java.util.List<? extends T>
而不是java.lang.List<T>
。
要在不切换到不变类型(例如 MutableList
)的情况下修复它,您应该在 List
类型上使用 @JvmSuppressWildcards
:
例如
class OrdersRepository: CacheEntity<List<@JvmSuppressWildcards Order>>
我只添加了你完整代码的一个片段,你应该检查你的列表用法并在它们上使用 @JvmSuppressWildcards
。