这个强大的枚举

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

今天我想重温一下 Java 的著名特性——我们将看看枚举。

让我们从一个定义开始:

枚举 - 项目的集合,是该集合中所有项目的完整有序列表。

[维基百科-枚举]


听起来很简单是不是?即使如此,Java 中的枚举允许我们做很多事情,它是一种非常棒的语言特性,可以提高我们代码的质量。

让我们从基础开始,然后我们将检查 Java 中的枚举到底有多强大。


类型安全

这意味着你的枚举将有一个类型,你不能分配任何除了在枚举常量中指定的值。

更具体地说,使用以下枚举:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

写这样的东西没有问题:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

但:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

最终会是:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


自己的命名空间

这意味着即使一个枚举中的值与其他枚举重叠:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

两者都有效,可以同时使用。


常量是隐式静态和最终的

不可能做这样的事情:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

它只会以:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


可在 switch 语句中使用。

所以不要害怕写这样的东西:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

它会起作用 :) 在代码中和现实生活中一样 :)


无法使用 new 创建实例

正如 文档 中所写:

枚举类型的构造函数必须是包私有或私有访问。它会自动创建在枚举主体开头定义的常量。您不能自己调用​​枚举构造函数。

这是(根据定义)因为 Enum 应该是唯一负责返回预定义实例的人。

为防止任何其他修改:

Enum 中的最终克隆方法确保枚举常量永远不会被克隆,序列化机制的特殊处理确保永远不会因反序列化而创建重复实例。枚举类型的反射实例化是被禁止的。这四件事共同确保枚举类型的实例不存在于枚举常量定义的实例之外。

[JLS-枚举]

但如果你无论如何都想尝试,你会得到:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


我们不费吹灰之力得到了什么?

看一下简单的枚举:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


不是那么令人印象深刻不是吗?但别担心,即使是这样简单的构造也提供了一些有用的方法:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

name() 和 ordinal() 方法是简单的 getter,它们返回构造函数中给定的值,这些值由编译器发出以响应枚举类型声明。

构造函数不能被程序员调用,它的声明如下所示:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


方法 toString(),直到未被覆盖,将返回枚举常量的名称,这与 name() 返回的内容几乎相同。


方法 valueOf() 查找名称与给定值相同的枚举并返回它。


还有一个值得一提的方法:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


我相信在看了测试之后就不需要更多的解释了:)


在本段中,我描述了最重要的 Enum 方法,我们通过使用 enum 关键字获得了这些方法。

让我们看看我们可以用它做更多的事情。


我自己的方法

枚举不一定只是一个简单的项目列表。您可以将自己的方法添加到其中或/和提供自己的构造函数。

值得一提的是,构造函数必须是私有的,并且您不能执行父级(枚举)的构造函数,无需额外的努力即可完成。


类别枚举展示了如何做到这一点:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


信不信由你,但它确实有效,如果你想验证它,只需运行以下测试:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


如果您不熟悉 JUnit 中的 @Parameterized 注释,请查看 此处 以获取快速介绍。


给我一点抽象

创建抽象方法有时真的很有用,这就是为什么在枚举中也可以这样做的原因:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

现在运行:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


和?一切都是绿色的,不是吗?


接口呢?

我们知道接口在设计良好的代码中有多么重要。这就是为什么 Enums 允许实现尽可能多的接口,就像普通类一样,这对我们所有人来说都是个好消息。


假设我们有以下接口:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


现在我们将更改枚举定义并添加有关实现新添加接口的部分:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

现在再次运行我们的测试。一切还好吗?应该 :)


继承呢?

好的,所以可以实现接口并创建抽象方法,那么继承呢?

我相信目前不需要任何解释,因为我已经在上面的一段中提到了一些关于 parent 的内容,当我写 name() 和 ordinal() 方法和构造函数并在其中调用 parent 时,但是确切地说...


正如 教程 中所写:

所有枚举都隐式扩展了 java.lang.Enum。由于 Java 不支持多重继承,因此枚举不能扩展任何其他内容。


空枚举

出于好奇,我还想写一下,可以创建一个空枚举,编译器不会有任何问题。这意味着下面的枚举是有效的:


 enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}


作为旁注,我想告诉你,我从来没有使用过它,所以如果你有任何好的例子表明创建这样的枚举有意义,请在评论中与我分享,我将不胜感激:)



今天就到此为止。

我希望你喜欢它并学到新的东西。或者至少刷新你的记忆:)

我在等你的评论。


并且...祝您利用枚举的力量好运!