编程Kotlin开发者

描述Kotlin中的enum类机制:什么是enum class,它与Java有何不同,enum有哪些特性和限制,如何添加自己的功能,序列化和比较时可能出现哪些细节。请举例说明。

用 Hintsage AI 助手通过面试

答案。

在Kotlin中,枚举(enum class)允许声明一组有限的值,并可以通过方法和属性扩展它们。

主要要点:

  • enum类的声明与Java类似,但语法更加严格:
    enum class Direction { NORTH, SOUTH, WEST, EAST }
  • enum元素是单例,对应类的实例。
  • 可以在enum中定义额外的属性和方法:
    enum class Color(val rgb: Int) { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF); fun containsRed() = (rgb and 0xFF0000 != 0) }
  • 可以通过名称(Color.RED.name)、索引(ordinal)访问每个值,并通过values()获取完整列表。
  • 在Kotlin中,enum类不能被继承,但可以实现接口。
  • 与Java的不同之处在于,无法显式从enum派生类,不能使用嵌套集合;
  • Kotlin中的枚举默认不通过标准工具(如Gson或Jackson)序列化——需要特殊适配器/注解。

比较enum:

  • 使用==(身份)比较枚举,因为元素是唯一的。
  • 在序列化时名称可能会改变,最好明确指定值(存储值模式)。

有陷阱的问题。

可以在Kotlin的enum类中定义抽象方法,像在Java中那样,让每个元素重写它吗?

正确答案: 可以在enum风格中声明抽象方法,每个元素必须提供自己的实现!

enum class State { START { override fun next() = RUNNING }, RUNNING { override fun next() = STOPPED }, STOPPED { override fun next() = STOPPED }; abstract fun next(): State }

由于不知道本主题细节而导致的实际错误示例。


故事

在从Java迁移到Kotlin时,团队试图像普通类一样继承新的enum类——结果发现枚举不能继承,破坏了架构。必须彻底改变状态机模块化的方法。


故事

为了在数据库中存储值,使用了元素的名称(enum.name),但在重构中枚举元素被重命名——数据库中的数据与新逻辑不符,导致一致性丧失(未实现存储值模式)。


故事

为了通过Gson序列化enum类,忘记连接自定义TypeAdapter。在生产环境中,服务开始返回不正确的JSON值,因为标准解析器序列化了错误的字段(ordinal或name),导致微服务之间的反序列化不一致。