Mic*_*rdo 6 java generics interop kotlin
我在Kotlin中有一个方法,它返回一个通用列表的Rx Observable:
public fun getObservable(): Observable<List<FooBar>> {
return Observable.just(theList)
}
Run Code Online (Sandbox Code Playgroud)
因为Kotlin list trait被定义为List<out T>,所以Java会将返回类型视为Observable<List<? extends FooBar>>.
有没有办法告诉Kotlin编译器Java应该看到这个Observable<List<FooBar>>?
http://kotlinlang.org/docs/reference/generics.html
已更新以正确显示问题.
您可以使用JvmWildcard和JvmSuppressWildcards注释控制Java如何看待Kotlin泛型.它被添加到Kotlin 1.0 Beta 4中(见公告).
此更改意味着您的代码已经更改为正常,并且不再生成通配符.因为新的默认设置是在许多情况下不使用它们,您可以使用注释将它们带回来,或者在不需要时禁止它们.
这一变化的公告表明:
Java通配符
Kotlin如何翻译变体类型存在问题,例如List是Java应该是List还是List.除了细微之处,我们做了以下工作:
- 默认情况下,我们不会在返回类型中生成通配符,并且它们没有任何意义
- 当需要通配符时,可以使用类型注释强制其存在:List <@JvmWildcard String>始终是Java中的List
- 当我们需要删除通配符时,我们可以使用@JvmSuppressWildcards(这可以用于包含它的类型或任何声明)
例子:
fun foo(l: List<String>) // in Java: List<String> (String is final)
fun foo(l: List<@JvmWildcard String>) // in Java: List<? extends String>
interface Open {}
fun bar(p: List<Open>) // in Java: List<? extends Open> (Open is not final)
@JvmSuppressWildcards
fun bar(p: List<Open>) // in Java: List<Open>
Run Code Online (Sandbox Code Playgroud)
如果您仍然遇到问题,请将此问题应用于您的问题:
@JvmSuppressWildcards
public fun getObservable(): Observable<List<FooBar>> {
return Observable.just(theList)
}
Run Code Online (Sandbox Code Playgroud)
编辑:此行为在 Kotlin Beta 4 中已更改。请参阅 Jayson Minard 的回答。
我可以看到两个选项:
第一个是返回一个Observable<MutableList<FooBar>>. 由于 aList在 kotlin 中是不可变的,因此它被声明为List<out T>因为类型 T 的对象只能从中取出。
MutableList另一方面是 Java 真正的List等价物:因为它是可变的,所以被声明为MutableList<T>.
所以你的函数是:
public fun getObservable(): Observable<MutableList<FooBar>>
= Observable.just(theList)
Run Code Online (Sandbox Code Playgroud)
这个解决方案的问题是,如果你在 kotlin 中使用它,如果你只想拥有一个不可变列表的 Observable,那么你会授予对你的列表“太多”的访问权限。
第二种选择是在 java 中编写一个“代理”方法,使强制转换一劳永逸:
@SuppressWarnings("unchecked")
public static Observable<List<String>> _getObservable() { return (Observable) TestPackage.getObservable(); }
Run Code Online (Sandbox Code Playgroud)
这很丑陋,但它有效,而且不会破坏 kotlin
但是,我假设您正在使用 RxJava Observable,那么为什么不利用这个机会在 Java 中强制执行 kotlin 的不可变列表语义呢?
public static Observable<List<String>> _getObservable() {
return TestPackage.getObservable().map(new Func1<List<? extends String>, List<String>>() {
@Override
public List<String> call(List<? extends String> list) {
return Collections.unmodifiableList(list);
}
});
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1149 次 |
| 最近记录: |