前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java枚举(Enum)类型原理探求

Java枚举(Enum)类型原理探求

作者头像
用户7353950
发布2022-05-11 10:58:55
3230
发布2022-05-11 10:58:55
举报
文章被收录于专栏:IT技术订阅

Enum枚举类型

Enum的全写是Enumeration,这个词的翻译是列举、逐条陈述、细目。在程序语言中,枚举类型是一种特殊的数据类型(常用的数据类型比如字符串、整型),这种数据类型的变量值限定在固定的范围, 比如季节只有春夏秋冬,月份是12个。

Java中的枚举

枚举前时代

在Java语言中, 枚举类型从JDK1.5才开始提供。在这之前使用接口静态常量来实现相关功能(也可以是类静态常量),以季节为例:

在不使用枚举类之前,一般使用接口静态常量实现。比如:

```java

public interface Season {

public static final int SPRING = 1;

public static final int SUMMER = 2;

public static final int AUTUMN = 3;

public static final int WINTER = 4;

}

```

使用JUnit使用测试如下:

```java

@Test

public void noEnum() {

int i = 1;

Assert.assertTrue(Season.SPRING==i);

}

```

使用接口静态常量的方式比较难限定变量的范围,而且定义繁琐,功能也很有限,于是在Java 1.5 中定义了一个枚举类型:`java.lang.Enum`。

Java枚举的定义

类似类(class)和接口(interface)的定义,Java提供enum关键字用来定义枚举类,在IDEA中创建枚举类的菜单如下:

同样定义一个季节的枚举类, 代码可以简洁如下:

```java

package cn.osxm.jcodef.func.base;

public enum SeasonEnum {

SPRING, SUMMER, AUTUMN, WINTER

}

```

在枚举类中直接列出常量,常量遵循全部大写的规则。在上面的枚举类示例代码中,SPRING, SUMMER, AUTUMN, WINTER 是SeasonEnum的成员。

- 枚举成员默认是final、public、static (所以可以使用SeasonEnum.SPRING方式调用枚举成员)

- 每一个枚举类型成员都可以看作是枚举类的实例 (SeasonEnum.SPRING的类型也是SeasonEnum)

在JUnit使用测试如下:

```java

@Test

public void enumBase() {

SeasonEnum season = SeasonEnum.SPRING;

Assert.assertTrue(season.equals(SeasonEnum.SPRING));

}

```

Java 枚举类的特性

Java枚举类的特性有:

- 枚举可以实现接口,但不能继承接口,也不能被继承。

- 枚举类是final的,所以不能继承。

- 枚举类的构造方法是私有的

- 枚举成员是静态、final和public

- 枚举成员是枚举类的实例

但是从上面SeasonEnum枚举类的定义来看,完全看不出这些特性,这些特性是怎么来的呢?请看下面的原理探求。

Java枚举类实现的原理探求

ava枚举类型的奥秘就在编译阶段,枚举类在编译后会生成了一个扩展java.lang.Enum的类。这个可以通过JDK自带的javap工具来反编译生成的.class文件。对上面的生成的SeasonEnum.class文件进行反编译,因为这个文件的包路径是cnosxmjcodeffuncbase,所以在命令行使用如下命令:

```js

javap -p cnosxmjcodeffuncbaseSeasonEnum.class

```

- `-p`参数的意思是反编译代码中包含私有的方法, p是private的意思。

从控制台输出的反编译后的源码可以看出:

- 自定义的枚举类会自动继承`java.lang.Enum`类

- 每个成员变量都会被转换为 private static final的枚举类型的实例

- 自动添加private的构造函数

从反编译后的源码就不难理解Enum的特性了。

注意:使用专门的Java反编译工具,比如JD GUI、luyten等对Eumn进行反编译的效果接近源码的效果,无法看到继承等特性,JD-GUI反编译的效果和源码时一致的,这也说明使用JD GUI来进行实际的反编译还是不错的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT技术订阅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档