我不确定“失败”是否正确,但这是我面临的问题。我花了相当多的时间将其重现为最小的示例,所以到这里去了:

class BaseParameterizedType<T>

fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U {
     TODO()
}

fun example(arg: KClass<out BaseParameterizedType<*>>)) {
    getSpecific(arg.innerType)
}

好的,因此上面的代码在“TODO”处失败,但是,如果不存在并且函数正常返回,则它肯定会失败,并出现空指针异常。我尽力找出出了什么问题,所以我转向了反编译的Java代码(来自kotlin字节码):
public static final void example(@NotNull KClass arg) {
  Intrinsics.checkParameterIsNotNull(arg, "arg");
  getSpecific(arg.getInnerType());
  throw null;  // <-- The problem
}

如果我将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());
    }
    

    现在,假设在调用站点,我将其更改为:
    getSpecific(BaseParameterizedType::class)
    

    那么这也不会生成throw null子句。因此,我猜测这与kotlin有关,假设此强制转换将始终失败或存在不确定的信息来进行推断?

    因此,我们知道arg.innerTypeKClass<out BaseParameterizedType<*>>,并且我们在接受KClass<in BaseParameterizedType<*>>的站点上使用它,所以U为什么不推断为BaseParamterizedType<*>>。从字面上看,这是唯一会匹配的类型。

    同时,我认为仅生成throw null语句难以调试。 stacktrace只会指向存在getSpecific的行,祝您好运,找出空指针异常来自何处。

    最佳答案

    当所推断的类型为Nothing(在您的情况下)时,这是一个与类型推断角案例处理有关的已知问题:

    Kotlin未能成功将上行链路转换为推断的(现场)参数-LMLPHP

    由于对投影KClass<in U>KClass<out BaseParameterizedType<*>>进行了强制性尝试,因此推断的行为如此。

    基本上,同时投影一个out的类型意味着in Nothing(因为实际的type参数可以是任何子类型,并且不能安全地传递任何内容)。因此,为了使KClass<out BaseParameterizedType<*>>KClass<in U>匹配,编译器选择U := Nothing,这意味着函数调用也返回Nothing

    备注:Foo<out Any>投影不能将Foo<in T>T := Any匹配,因为传递给Foo<out Any>的值的实际类型参数可以是Int。然后,如果Foo<T>在其某些功能中接受T,则允许上述匹配还将使您可以将Any实例传递到Foo<Int>不需要它们的地方。实际上,由于in Nothing投影类型的未知性质,因此out成为匹配它们的唯一方法。

    之后,对于返回Nothing的函数调用,编译器将插入该throw null字节码以确保执行不会继续(评估Nothing型表达式is supposed to never finish correctly)。

    查看问题:KT-20849KT-18789

    10-05 18:47