Koltin泛型声明 – 站点方差<T>构造

我正在阅读kotlin没有通配符的原因( https://kotlinlang.org/docs/reference/generics.htm l)。 这一切都来到声明网站的变化。 我们有<in T><out T>结构应该取代通配符。 我想我明白了<out T>是如何运作的,但我却在<in T>遇到麻烦。
所以在java中,我们可以这样写:

 public List<? extends Number> list1; public List<? super String> list2; 

初始化后的第一种情况变成只读列表(虽然不是完全不可改变的原因,我们可以清除它),如果我们把每个元素都视为数字,就可以读取它们。
第二种情况是只写(尽管我们可以阅读它,如果我们把每个元素作为对象)。 我们可以写那里字符串和它的子类。
在Kotlin中,我能够像这样使用<out T>重新创建list1示例:

 class Service { val container = Container(mutableListOf("1", "2", "3")) } class Container<T>(var list1: MutableList<out T>) 

最后我尝试了一些类似于<in T>东西,认为我可以重新创建list2的例子,但是我失败了: 在这里输入图像描述

有人可以向我解释如何在Kotlin中实现我的list2例子吗? 我应该如何正确使用<in T>结构?

Kotlin List<E>不等于Java List<E> 。 Java列表具有变异功能,而Kotlin列表是只读的。 它是Kotlin MutableList<E> ,等同于Java列表。

接下来,看一下List<E>声明 :它的类型参数是协变的( out E ),并且声明站点的变量不能被使用站点变量覆盖,这就是为什么你不能在List<in T>有一个List<in T>

此外,声明站点方差out E意味着E永远不会出现在一个in -position(没有E类型的函数参数,也不是E类型的可变属性),事实上,由于List<E>是只读的,不会将E带入其任何功能(*)

你可以转换你的例子来使用MutableList<E>来代替:

 class Container2<T>(var list2: MutableList<in T>) 

MutableList<E>接口具有E不变性,而use-site中的MutableList<E>不与声明网站方差冲突。

(*)实际上, 它只是使用标有@UnsafeVariance注解的参数,它简单地抑制了方差冲突,更多关于它的信息可以在这里找到。


另外,一个小的评论:

这一切都来到声明网站的变化。 我们有<in T><out T>结构应该取代通配符。

这实际上是用于替换Java通配符的使用站点差异。 声明站点的差异只适用于类型参数声明(类型被定义的地方),当它是时,类型的所有用法都会有差异(例如当你使用List<CharSequence> ,它实际上是一个List<out CharSequence>因为List<out E>的声明站点变化)。 因此,使用地点差异对于通用类型的特定用途而言。