考虑以下Kotlin接口:
interface Box<out T : SomeType> {
val item: T
}
用Kotlin来实现这一点看起来像这样:
data class BoxImpl<out T : SomeType>(override val item: T) : Box<T>
现在我想把这个接口转换成Java:
public interface Box<T extends SomeType> {
T getItem();
}
但在Kotlin中实现这一点会带来一个问题:
data class BoxImpl<out T : SomeType>(private val item: T) : Box<T> {
override fun getItem(): T {
return item
}
}
问题是Kotlin编译器抱怨T
在Java接口上是不变的,但是在实现上是协变的。
那么,如何在Java中指定out
(协变)方差呢?
另外,如何指定in
(逆变)方差?
2条答案
按热度按时间pxq42qpu1#
Java不像Kotlin那样有声明位置的变量,也就是说,你不能在你 * 声明 * 一个类型的时候指定它的变量,但是,它有使用位置的变量--你 * 可以 * 在你 * 使用 * 一个类型的时候指定变量,例如,作为一个变量的类型。
例如,
类似于:
(The其助记符为PECS。)
但是,一个关键的区别是,您可以将
null
传递到Javabar
变量的方法中,但是你不能把任何东西传递到Kotlin
bar
中--它实际上需要Nothing
!如果您试图在Kotlin代码中使用Java中的泛型类型,我认为您现在必须将其设置为
@UnsafeVariance
以抑制编译器错误。还有一些讨论是关于添加注解Java类型参数的能力,以便Kotlin编译器知道它们的变化。参见this和this。希望我们将来能得到它。尽管这不会改变Java中没有声明站点变化的事实。
abithluo2#
Java不像Kotlin那样支持声明位置的变量,它只支持使用位置的变量,换句话说,变量只能用在变量和参数类型上,不能用在类/接口定义中。
所以在Java中,你可以指定你的接口和类定义,而不需要变量,每次你需要变量的时候,你都可以用它来声明变量。
协方差使用
? extends
,反方差使用? super
,例如: