0

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

List<? extends MyMarkerInterface> => MutableList<out MyMarkerInterface>

当杰克逊在将数据编译到这个变量(列表)之后设置它就可以了。当我尝试从 Kotlin 代码添加项目时,Kotlin 说我只能添加 Nothing(类型)项目。

那么如何在 Kotlin 中放入 MyMarkerInterface 的 List 子项?

4

2 回答 2

0

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

于 2020-04-28T12:41:00.153 回答
0

这是关于方差的。

(因为 Kotlin 区分了可变列表和不可变列表,所以它比 Java 更严格,所以你不能总是直接比较。)

假设您引用了一个MutableList<out MyMarkerInterface>. 该参数等效于 Java 的<? extends MyMarkerInterface>,并且意味着您有一个可变列表MyMarkerInterface 或某个子类型。但是你不知道是哪个子类型;它可以是实现你的接口的任何类型。

它可能是一个可变的列表MyImplementingClassA;所以你显然不能添加一个实例MyImplementingClassB而不冒违反其类型安全的风险。反之亦然。事实上,在不了解它的类型的情况下,向它添加任何东西是不安全的。这就是 Kotlin 不让你这么做的原因。(这样做的方式是推断 type Nothing,它是“底部”类型并且没有值。)

但是,如果您想列表中获取一个值,您知道它是 的某个子类型MyMarkerInterface,因此您可以愉快地将其视为MyMarkerInterface参考。

这就是为什么out方差意味着列表是一个生产者:它可以安全地为您生成值,但它不能消耗值,因为没有类型是安全的。

这与方差完全相反in,它相当于 Java 的? super.

(这当然是PECS的要点。确切的措辞仅适用于 Java —— Kotlin 的等价物是“生产者出,消费者入”,这可能太明显了,不需要首字母缩写词!——但原理是一样的。)

既是生产者又是消费者的唯一安全方法是保持不变:平淡无奇MutableList<MyMarkerInterface>。这样,您就知道可以将MyMarkerInterface值取出放入MyMarkerInterface

s 的情况有所不同List,它们在 Kotlin 中是不可变的。(或者更确切地说,你不能通过那个引用改变它们;你可以通过其他方式改变它们。)因为那个引用不会让你把值放进去,所以 aList不是消费者,只是生产者,所以out方差很好

——</p>

您的问题没有提供任何细节,但您提到了初始化。最常见List的做法可能是预先创建具有所有值的 a - 通过调用listOf()或构造函数,或者作为map()或类似操作的结果。

但是,您也可以创建某种类型的MutableList,根据需要进行设置,然后将其向上转换为List(它是 的超接口MutableList),例如:

val ml = ArrayList<MyImplementingClassA>()
// …some computation which calls ml.add()…
val l = ml as List<out MyMarkerInterface>

…尽管在实践中,您通常不需要最后一行;Kotlin知道Lists 有差异,out因此如果需要它会自动向上ml转换。List<out MyMarkerInterface>

于 2020-04-28T20:57:49.200 回答