You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Kotlin根据defaultValue非空推断readOptional返回非空类型?

解决Kotlin readOptional函数的空类型推断问题

要实现当传入非空defaultValue时,函数返回非空类型、无需手动用!!强制转换的需求,可以通过泛型绑定返回值与参数类型的方式解决,具体实现如下:

优化后的函数实现

object CliUtils {
    var skipOptionalArgs = false

    fun <T : Any?> readOptional(variableName: String, defaultValue: T): T {
        if (skipOptionalArgs) return defaultValue
        
        val prompt = buildString {
            append("Provide the $variableName (optional")
            defaultValue?.let { append(", default: $it") }
            append("): ")
        }
        print(prompt)
        
        return readln().takeIf { it.isNotEmpty() } as T? ?: defaultValue
    }

    // 为无默认值的场景提供重载
    fun readOptional(variableName: String): String? {
        if (skipOptionalArgs) return null
        print("Provide the $variableName (optional): ")
        return readln().takeIf { it.isNotEmpty() }
    }
}

效果说明

  • 传入非空默认值时,返回类型自动推断为非空:
    // inputName 类型为 String,而非 String?
    val inputName = CliUtils.readOptional("input name", "Input")
    
  • 传入null作为默认值,或调用无参数重载时,返回类型为String?:
    // inputName 类型为 String?
    val inputName = CliUtils.readOptional("input name", null)
    val optionalInput = CliUtils.readOptional("optional input")
    

原理说明

原函数返回类型固定为String?,编译器无法根据defaultValue的非空性动态调整返回类型。而泛型版本将返回类型T与defaultValue的类型绑定:

  • 若defaultValue是非空String,则T被推断为String,函数返回非空值;
  • 若defaultValue是null(即类型为String?),则T被推断为String?,函数返回可空值。

关于契约的补充说明

Kotlin的契约(Contracts)目前仅支持有限的断言逻辑,无法直接声明"当defaultValue非空时返回值必非空"这类条件式关联,因此泛型方案是更稳定可靠的选择。若一定要尝试契约,需启用@ExperimentalContracts注解,但无法完全替代泛型的类型绑定效果。

内容的提问来源于stack exchange,提问作者Rik Schaaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 02:02:11