Kotlin List<E>
不等同于JavaList<E>
。 Java 列表具有变异函数,而 Kotlin 列表是只读的。这是科特林MutableList<E>
这相当于 Java 列表。
接下来,看看List<E>宣言 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html:它的类型参数是协变的(out E
),并且声明站点差异不能被使用站点差异覆盖,这就是为什么你不能拥有List<in T>
.
Moreover, the declaration-site variance out E
means that E
never appears in an in
-position (there's no function parameter of type E
and no mutable property of type E
), and indeed, since List<E>
is read-only, it doesn't take E
into any of its functions (*).
您可以将示例转换为使用MutableList<E> https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/index.html反而:
class Container2<T>(var list2: MutableList<in T>)
The MutableList<E>
接口有其E
不变,并且in
- 使用地点的投影与声明地点的差异不冲突。
(*) Actually, it does https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/contains.html, but only using the parameters that are marked with the @UnsafeVariance https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unsafe-variance/index.html annotation, which simply suppresses the variance conflict, more about it can be found here https://blog.jetbrains.com/kotlin/2015/10/kotlin-1-0-beta-candidate-is-out/.
另外,还有一点小意见:
这一切都源于申报地点的差异。我们有<in T>
and <out T>
应取代通配符的结构。
它实际上是使用站点差异取代了 Java 通配符。声明站点差异仅应用于类型参数声明(定义类型的地方),并且当它是时,该类型的所有用法都将具有该差异(例如,当您使用List<CharSequence>
,它实际上是一个List<out CharSequence>
由于声明地点的差异List<out E>
)。因此,使用地点差异适用于通用类型的特定用法。