gpt4 book ai didi

kotlin - 声明站点差异可能导致 ClassCastException

转载 作者:行者123 更新时间:2023-12-02 12:55:06 43 4
gpt4 key购买 nike

Kotlin 引入了 here 中描述的声明站点差异.

在某些情况下,泛型参数的 out/in 关键字可能会导致 ClassCastException。我的程序如下所示。

fun main(args: Array<String>) {
var l: List<String> = mutableListOf("string")
demo(l)
println("======")
for (s in l) {
println(s)
}
}

fun demo(strs: List<String>) {
val objects: List<Any> = strs // This is OK, since T is an out-parameter
if (objects is MutableList) {
val obs: MutableList<Any> = objects as MutableList<Any>
obs.add(TextView())
}
}

输出:
Exception in thread "main" java.lang.ClassCastException: com.kotlin.demo.clzz.TextView cannot be cast to java.lang.String
at com.kotlin.demo.clzz.Declaration_Site_VarianceKt.main(Declaration-Site-Variance.kt:14)
======
adn

使用 out/in 关键字的方式是推荐的做法吗?为什么?

最佳答案

您的代码可以在没有任何警告的情况下编译,这是因为 declaration-site variance仅在 Kotlin 中可用。

This is in contrast with Java's use-site variance where wildcards in the type usages make the types covariant.



例如 2 Soruce接口(interface)使用 declaration-site variance在 Kotlin :
interface Source<out T> 
interface Source<in T>

两者都是 Source接口(interface)将在 Java 中生成相同的源代码,如下所示:
//                      v---`T extends Object` rather than `? extends T` 
public interface Source<T>{ /**/ }

这是因为通配符 ?在 Java 中用作类型参数而不是类型参数。 TSource<T>类型参数? extends StringSource<? extends String>类型参数 .

所以如果你使用 type projections制作 objects强制到 List<out Any> ,则编译器将报告 UNCHECKED_CAST 警告,例如:
fun demo(strs: List<String>) {
// v--- makes it explicitly by using out type proejction
val objects: List<out Any> = strs
if (objects is MutableList) {
// v--- an UNCHECKED_CAST warning reported
val obs: MutableList<Any> = objects as MutableList<Any>
obs.add(TextView())
}
}

换句话说,您不能分配 List<out Any>MutableList<Any> .否则,您将收到编译错误。例如:
fun demo(strs: List<String>) {
val objects: List<out Any> = strs
if (objects is MutableList) {
// v--- ? extends Object
//ERROR: can't assign MutableList<out Any> to Mutable<Any>
// v ^--- Object
val obs: MutableList<Any> = objects
obs.add(TextView())
}
}

中频您分配 objectsMutableList<out Any>变量,你会发现你不能添加任何东西,因为你不能创建 Nothing在 Kotlin 中。例如:
fun demo(strs: List<String>) {
val objects: List<out Any> = strs
if (objects is MutableList) {
// v--- down-casting to `MutableList<out Any>`
val obs: MutableList<out Any> = objects
// v---ERROR: can't be instantiated
obs.add(Nothing())
}
}

Q: Is the way to use out/in keywords a recommended practice?



Java 描述了 how to use a wildcard它也适用于 Kotlin。

一个“ in ”变量,注意“ in ”这里是 ? extends T Kotlin 也是如此出方差:

An "in" variable serves up data to the code. Imagine a copy method with two arguments: copy(src, dest). The src argument provides the data to be copied, so it is the "in" parameter.



一个“ out ”变量,注意“ out ”在这里是 ? super T Kotlin 也是如此在 方差:

An "out" variable holds data for use elsewhere. In the copy example, copy(src, dest), the dest argument accepts data, so it is the "out" parameter.

关于kotlin - 声明站点差异可能导致 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45377382/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com