使用密封类时When表达式出现Non-Exhaustive Error的原因咨询
密封类搭配when表达式出现Non-Exhaustive Error的原因分析
你遇到的这个报错,核心原因是Kotlin编译器无法在当前代码作用域中确认你已经覆盖了密封类的所有直接子类,即便你主观认为已经覆盖了所有情况。具体可能的触发场景及原因如下:
常见触发原因
子类与密封类不在同一文件/合法作用域内
Kotlin对密封类的子类有严格的作用域要求:- Kotlin 1.5之前,密封类的所有直接子类必须和父类放在同一个文件中,或是作为密封类的嵌套成员。
- 1.5版本之后允许子类放在同一模块的其他文件,但要求子类可见性为
internal或private,且编译器需在当前作用域能看到所有子类。如果你的Car或Bicycle是其他文件中定义的public类,编译器无法确保没有未被定义的子类存在,因此会判定when表达式非穷尽,要求添加else分支。
IDE缓存或编译异常
有时候IDE缓存会出现逻辑错误,明明代码符合规则却报错。这种情况可以尝试清理IDE缓存(比如IntelliJ系列的File -> Invalidate Caches...)后重新编译。Kotlin版本或依赖冲突
若项目中混合了不同版本的Kotlin插件、标准库依赖,可能导致编译器行为异常,出现不符合官方文档描述的报错。
解决办法
规范子类作用域:将密封类的所有直接子类和父类放在同一个文件中,或是作为密封类的嵌套成员,示例如下:
// 同文件写法 sealed class Vehicle data class Car(val manufacturer: String, val model: String) : Vehicle() data class Bicycle(val manufacturer: String) : Vehicle() fun getVehicle(vehicle: Vehicle) = when (vehicle) { is Car -> "${vehicle.manufacturer} - ${vehicle.model}" is Bicycle -> vehicle.manufacturer // 此时编译器会识别所有子类,无需else分支 }或者嵌套类写法:
sealed class Vehicle { data class Car(val manufacturer: String, val model: String) : Vehicle() data class Bicycle(val manufacturer: String) : Vehicle() } fun getVehicle(vehicle: Vehicle) = when (vehicle) { is Vehicle.Car -> "${vehicle.manufacturer} - ${vehicle.model}" is Vehicle.Bicycle -> vehicle.manufacturer }清理缓存并重新编译:如果确认代码符合规则仍报错,尝试清理IDE缓存后重新构建项目。
统一Kotlin版本:检查项目中Kotlin插件、标准库的版本是否一致,避免依赖冲突导致的编译器异常。
内容的提问来源于stack exchange,提问作者Tonnie
相关产品推荐
相关产品推荐

