首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlin和Java PECS

Kotlin和Java PECS
EN

Stack Overflow用户
提问于 2020-04-28 20:09:26
回答 2查看 125关注 0票数 0

所以我目标是在Kotlin中使用类似于Java PECS的构造:

代码语言:javascript
复制
List<? extends MyMarkerInterface> => MutableList<out MyMarkerInterface>

当Jackson在编译数据到这个变量(List)后设置时,它是正常的。当我尝试从Kotlin代码添加项目时,Kotlin说我只能添加任何(类型)项目。

那么我如何在Kotlin中放入MyMarkerInterface的子列表呢?

EN

回答 2

Stack Overflow用户

发布于 2020-04-28 20:41:00

完全删除,它可以很好地工作,但在Kotlin之后从字节码反编译代码时没有"?扩展“

票数 0
EN

Stack Overflow用户

发布于 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的超级接口),例如:

代码语言:javascript
复制
val ml = ArrayList<MyImplementingClassA>()
// …some computation which calls ml.add()…
val l = ml as List<out MyMarkerInterface>

…虽然在实践中,你通常不需要最后一行;,Kotlin knowsLists有out方差,所以如果需要,它会自动将ml向上转换为List<out MyMarkerInterface>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61479851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档