Kotlin:基于函数 return 值的未经检查的类型推断

Kotlin: unchecked type inference based on function return value

在 Java 中,您可以编写这样的方法,它不会抛出任何转换警告并根据 return 类型推断类型:

public static <T> T getService(final String name) {
    return (T) appCtx.getBean(name);
}

以下是一些用法示例:

public static StatusService getStatusService() {
    return getService("statusService");
}

public static VenueService getVenueService() {
    return getService("venueService");
}

现在我尝试将其转换为 Kotlin 并想出了这个:

fun <T> getService(name: String): T {
    return appCtx?.getBean(name) as T
}

但是这里我收到了强制转换警告:

Unchecked cast: Any? to T

好的,在 Whosebug 上浏览了一些之后,我发现你可以用注释关闭它:

@Suppress("UNCHECKED_CAST")

虽然我不确定这是一个干净的解决方案。

我的问题是:当您通过 Kotlin 中的 return 类型推断类型时,有没有办法避免这种未经检查的类型转换警告?如果可以,你怎么做。

更新 1

经过一些回答和评论( 和 Marko Topolnics 的评论)后,我将我的代码更改为:

inline fun <reified T> getService(name: String): T {
    requireNotNull(appCtx) { "Application context has not been set." }
    return appCtx?.getBean(name) as T
}

此代码消除了未经检查的转换警告并改进了错误处理。

更新 2

根据 Alexey Romanov 的建议,我删除了 requireNotNull 并将代码更改为:

var appCtx: ApplicationContext by Delegates.notNull()

private inline fun <reified T> getService(name: String): T {
    return appCtx.getBean(name) as T
}

实际上甚至 java 编译器(至少从 JDK 8u131 开始)也会发出类似的警告。所以 kotlinc 遵循相同的路径。

这就是为什么未检查强制转换而 Kotlin 的警告是正确的原因:

// Java
Object service = <StatusService> getService("venueService");

您会注意到它编译并且在执行时不会抛出异常。这是因为类型擦除将 (T) appCtx.getBean(name) 变成了 (Object) appCtx.getBean(name) 并且这种转换显然总是成功的。

reified T 不会发生这种情况,因为 T 在调用站点是已知的,因此会检查那里的转换。