您现在的位置是:首页 > 正文

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

2024-02-01 02:28:08阅读 4

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

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

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

  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使用测试如下:

  @Testpublic void noEnum() { int i=1; Assert.assertTrue(Season.SPRING==i);}

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

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

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

  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使用测试如下:

  @Test public void enumBase() { SeasonEnum season=SeasonEnum.SPRING; Assert.assertTrue(season.equals(SeasonEnum.SPRING)); }

  Java枚举类的特性有:

  枚举可以实现接口,但不能继承接口,也不能被继承。枚举类是final的,所以不能继承。枚举类的构造方法是私有的枚举成员是静态、final和public枚举成员是枚举类的实例

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

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

  javap -p cn\osxm\jcodef\func\base\SeasonEnum.class-p参数的意思是反编译代码中包含私有的方法, p是private的意思。

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

  自定义的枚举类会自动继承java.lang.Enum类每个成员变量都会被转换为 private static final的枚举类型的实例自动添加private的构造函数 从反编译后的源码就不难理解Enum的特性了。

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

网站文章

  • 《利息理论》指导 TCP 拥塞控制

    《利息理论》指导 TCP 拥塞控制

    名著的效果就是提供高强度思维训练,读懂就形成了反射,可融会贯通,相对而言,畅销书就没这效果,过程中可能觉得很哇塞,但主题还是散。端到端 cc 算法作为借贷实体,它有欲望和节制,希望获得更大带宽却不想消...

    2024-02-01 02:28:00
  • 详解String,StringBuffer,StringBuilder

    详解String,StringBuffer,StringBuilder

    一、通过代码测试三者进行字符串拼接的性能对String,StringBuffer,StringBuilderString,StringBuffer,StringBuilderString,String...

    2024-02-01 02:27:32
  • Collections.unmodifiableMap 用法解析

    Collections.unmodifiableMap 用法解析

    返回指定映射的不可修改视图。 通俗的讲就是:产生一个只读的Map,当你调用此map的put方法时会抛错。 public static Map unmodifiableMap(Map m) 此方法允许模块为用户提供对内部映射的“只读”访问。 在返回的映射上执行的查询操作将“读完”指定的映射。 试图修改返回的映射(不管是直接修改还是通过其 collection 视图进行修改)将

    2024-02-01 02:27:24
  • 短暂的“歧途”——写在短暂的第二份工作结束之时

    距离上一份工作结束总结才过去3个月,现在又要写第二份工作总结了。不用说,这份工作绝对是不太如意的。其中有不少需要总结的地方,希望读者也能从中吸取经验和教训。记事去年9月,还在第一份工作期间,跳槽的心就...

    2024-02-01 02:27:17
  • Jenkins部署新项目

    Jenkins部署新项目

    1、安装 Jenkins 下载jenkins-1.656.zip文件,进行安装 2、部署一个项目 2.1登录Jenkins http://127.0.0.1:xxxx/ 2.2新建 2.2.1构建一个maven项目 2.2.2输入SVN地址 2.2.4构建触发器 构建方式

    2024-02-01 02:27:10
  • Java读取输入流和文件内容——BufferedReader

    BufferedReader读取控制台输入从控制台读取数据readline() 方法关于 `try-catch` 语句的拓展 Java不像C那样直接用 scanf 即可从控制台读入数据,读取数据很麻烦...

    2024-02-01 02:26:41
  • Python使用定时任务

    Python使用定时任务

    【代码】Python使用定时任务。

    2024-02-01 02:26:33
  • 计算机卸载目录不让它显示,电脑删除文件时提示“无法删除文件夹 目录不是空的”怎么办?...

    计算机卸载目录不让它显示,电脑删除文件时提示“无法删除文件夹 目录不是空的”怎么办?...

    电脑使用久了之后会发现系统中存在很多没用的文件夹,此时最简单的方法就是直接删除,但是有时会在删除文件夹的时候出现“无法删除文件夹 目录不是空的”的提示,这是什么问题呢?现在本文就给大家分析该问题的原因...

    2024-02-01 02:26:27
  • 正向代理与反向代理通俗理解

    关于正向代理以及反向代理的理解。特别通俗,一看就懂。

    2024-02-01 02:26:00
  • MySQL if else的格式_mysql if--else

    MySQL if else的格式_mysql if--else

    case具有两种格式。简单case函数和case搜索函数。--简单case函数case sexwhen '1' then '男'when '2' the...

    2024-02-01 02:25:55