如何用Kotlin interop强制执行泛型

我在Kotlin中有一个方法,它返回一个通用列表的Rx Observable:

public fun getObservable(): Observable<List<FooBar>> { return Observable.just(theList) } 

因为Kotlin列表特征被定义为List<out T> ,所以Java会将返回类型看作Observable<List<? extends FooBar>> Observable<List<? extends FooBar>>

有没有办法告诉Kotlin编译器,Java应该将这个视为Observable<List<FooBar>>

http://kotlinlang.org/docs/reference/generics.html

已更新为正确显示问题。

编辑:这种行为在Kotlin Beta 4中已经改变。请参阅Jayson Minard的答案 。

我可以看到两个选项:

  • 首先是返回一个Observable<MutableList<FooBar>> 。 由于List在kotlin中是不可变的,所以它被声明为List<out T>因为类型T的对象只能被取出。
    另一方面, MutableList是Java的真正的List等价物:因为它是可变的,所以它被声明为MutableList<T>
    所以你的功能是:

     public fun getObservable(): Observable<MutableList<FooBar>> = Observable.just(theList) 

    这个解决方案的问题是,如果你在kotlin中使用它,如果你只想拥有一个不可变列表的Observable,那么你授予对列表的“太多”访问权限。

  • 第二种选择是在java中编写一个“代理”方法,这个方法是一劳永逸的:

     @SuppressWarnings("unchecked") public static Observable<List<String>> _getObservable() { return (Observable) TestPackage.getObservable(); } 

    这是丑陋的,但它的作品,它不会打破科特林

    不过,我假设你正在使用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); } }); } 

您可以使用JvmWildcardJvmSuppressWildcards注释来控制Java如何看待Kotlin泛型。 它被添加到Kotlin 1.0 Beta 4(见公告 )。

这个改变意味着你的代码已经改变了,并且不再生成通配符。 因为新的默认是在很多情况下不使用它们,您可以使用注释将它们带回,或者在不需要时将其禁用。

这一变化的公告指出:

Java通配符

Kotlin如何翻译变体类型有问题,例如List应该是Java中的列表还是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> 

所以把这个应用到你的问题上,如果你仍然有问题:

 @JvmSuppressWildcards public fun getObservable(): Observable<List<FooBar>> { return Observable.just(theList) }