我不确定'难以'是否是正确的词,但这是我面临的问题.我需要花费相当长的时间才能将其重现为最小的示例,所以这里有:
class BaseParameterizedType<T>
fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U {
TODO()
}
fun example(arg: KClass<out BaseParameterizedType<*>>)) {
getSpecific(arg.innerType)
}
Run Code Online (Sandbox Code Playgroud)
好的,所以上面的代码在'TODO'失败了,但是如果它不在那里并且函数正常返回,那么它肯定会因空指针异常而失败.我努力弄清楚出了什么问题,所以我转向反编译的Java代码(来自kotlin字节码):
public static final void example(@NotNull KClass arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
getSpecific(arg.getInnerType());
throw null; // <-- The problem
}
Run Code Online (Sandbox Code Playgroud)
如果我将函数签名更改getSpecific(clz: KClass<in U>) : U
为以下任何一种形式:
getSpecific(clz: KClass<out U>) : U
getSpecific(clz: KClass<U>) : U
getSpecific(clz: KClass<in U>) : BaseParameterizedType<*>
甚至是函数example(arg: KClass<out BaseParameterizedType<*>)
或者example(arg: KClass<BaseParameterizedType<*>>)
,然后生成的代码是:
public static final void example(@NotNull KClass arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
getSpecific(arg.getInnerType());
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们说在呼叫站点,我将其更改为:
getSpecific(BaseParameterizedType::class)
Run Code Online (Sandbox Code Playgroud)
那么这也不会产生throw null
条款.所以,我猜这与kotlin有关,假设这个演员总是会失败,或者有不确定的信息可以做出推断?
所以,我们知道这arg.innerType
是KClass<out BaseParameterizedType<*>>
我们在一个接受的网站上使用它KClass<in BaseParameterizedType<*>>
,所以为什么不U
推断BaseParamterizedType<*>>
.这实际上是唯一匹配的类型.
与此同时,我认为只是生成一个throw null
声明是难以置信的难以调试.堆栈跟踪只会指向存在的行,getSpecific
并且可以很好地确定空指针异常的来源.
当推断类型为Nothing
(并且在您的情况下)时,这是关于类型推断极端情况处理的已知问题:
KClass<in U>
由于对投影和的强制尝试,推断会以这种方式运行KClass<out BaseParameterizedType<*>>
。
基本上,out
同时投影类型意味着in Nothing
(因为实际类型参数可以是任何子类型,并且没有任何东西可以安全地传入)。因此,为了KClass<out BaseParameterizedType<*>>
与KClass<in U>
编译器匹配,选择U := Nothing
,这意味着函数调用Nothing
也会返回。
备注:Foo<out Any>
投影不能Foo<in T>
与匹配T := Any
,因为传递给 的值的实际类型参数Foo<out Any>
可以是,例如,Int
。然后,如果在其某些函数中Foo<T>
接受,允许上述匹配也将允许您将实例传递到不需要它们的地方。实际上,由于-projected 类型的未知性质,成为匹配它们的唯一方法。
T
Any
Foo<Int>
in Nothing
out
之后,对于Nothing
返回函数调用,编译器会插入该throw null
字节码以确保执行不会继续(评估Nothing
类型表达式应该永远不会正确完成)。
归档时间: |
|
查看次数: |
134 次 |
最近记录: |