所以我目标是在Kotlin中使用类似于Java PECS的构造:
List<? extends MyMarkerInterface> => MutableList<out MyMarkerInterface>当Jackson在编译数据到这个变量(List)后设置时,它是正常的。当我尝试从Kotlin代码添加项目时,Kotlin说我只能添加任何(类型)项目。
那么我如何在Kotlin中放入MyMarkerInterface的子列表呢?
发布于 2020-04-28 20:41:00
完全删除,它可以很好地工作,但在Kotlin之后从字节码反编译代码时没有"?扩展“
发布于 2020-04-29 04:57:49
这是关于variance的。
(因为Kotlin区分可变列表和不可变列表,所以它比Java更严格,所以您不能总是直接比较。)
假设您引用了一个MutableList<out MyMarkerInterface>. ,该参数相当于Java的<? extends MyMarkerInterface>,这意味着您有一个可变的MyMarkerInterface列表或一些子类型。但是您不知道是哪个子类型;它可以是实现接口的任何类型。
它可以是一个可变的MyImplementingClassA列表;因此,您显然不能在不违反其类型安全的情况下添加MyImplementingClassB的实例。或者反之亦然。事实上,在不了解其类型的情况下,将添加到它的. 中是不安全的,这就是为什么Kotlin不允许这样做。)(它这样做的方法是推断类型Nothing,它是“底层”类型,并且没有值。)
但是,如果您想从列表中获得一个值,那么您知道它是MyMarkerInterface的某个子类型,因此您可以很高兴地将其视为MyMarkerInterface引用。
这就是为什么out variance意味着这个列表是一个生产者:它可以安全地为您生成值,但它不能使用值,因为没有类型是安全的。
而Java的情况正好相反,它相当于in的? super。
(这当然是PECS. 的要点,确切的措辞只适用于Java -- Kotlin的等价物是“生产者出来,消费者进来”,这可能太明显了,不需要缩写!)-但原则是一样的。
同时作为生产者和消费者的唯一安全方法是成为 invariant:普通的老式MutableList<MyMarkerInterface>. 这样,你知道你可以得到MyMarkerInterface值,然后把MyMarkerInterface值放进去。
对于List来说,情况就不同了,它们在Kotlin中是不可变的。(或者更确切地说,你不能通过那个引用来改变它们;你可以通过其他方式改变它们。)因为那个引用不允许你把值放进去,所以out a 不是作为消费者,而只是生产者,所以 variance对于它是很好的。
-
你的问题没有给出任何细节,但你提到了初始化。最常见的可能是通过调用listOf()或构造函数,或者作为map()或类似操作的结果,使用预先拥有的所有值创建一个List。
但是,您也可以创建某种类型的MutableList,根据需要进行设置,然后将其向上转换为List (这是MutableList的超级接口),例如:
val ml = ArrayList<MyImplementingClassA>()
// …some computation which calls ml.add()…
val l = ml as List<out MyMarkerInterface>…虽然在实践中,你通常不需要最后一行;,Kotlin knows,Lists有out方差,所以如果需要,它会自动将ml向上转换为List<out MyMarkerInterface>。
https://stackoverflow.com/questions/61479851
复制相似问题