Java枚举的本质

2022年 3月 30日 62点热度 0人点赞

语法糖

Java 从 JDK1.5 开始支持枚举, 也就是说, Java 一开始是不支持枚举的, 就像泛型一样, 都是 JDK1.5 才加入的新特性. 通常一个特性如果在一开始没有提供, 在语言发展后期才添加, 会遇到一个问题, 就是向后兼容性的问题. 像 Java 在 1.5 中引入的很多特性, 为了向后兼容, 编译器会帮我们写的源代码做很多事情, 比如泛型为什么会擦除类型, 为什么会生成桥接方法, foreach 迭代, 自动装箱/拆箱等, 这有个术语叫 "语法糖", 而编译器的特殊处理叫 "解语法糖". 那么像枚举也是在 JDK1.5 中才引入的, 又是怎么实现的呢?

本质

一个枚举在经过编译器编译过后, 变成了一个抽象类, 它继承了 java.lang.Enum; 而枚举中定义的枚举常量, 变成了相应的 public static final 属性, 而且其类型就抽象类的类型, 名字就是枚举常量的名字, 同时我们可以在 Operator.class 的相同路径下看到四个内部类的.class 文件:

  • com/mikan/Operator$1.class
  • com/mikan/Operator$2.class
  • com/mikan/Operator$3.class
  • com/mikan/Operator$4.class

也就是说这四个命名字段分别使用了内部类来实现的; 同时添加了两个方法 values()valueOf(String). 我们定义的构造方法本来只有一个参数, 但却变成了三个参数;同时还生成了一个静态代码块.

其实编译器生成的这个静态代码块做了如下工作:

  • 分别设置生成的四个公共静态常量字段的值
  • 编译器还生成了一个静态字段$VALUES, 保存的是枚举类型定义的所有枚举常量

构造方法为什么增加了两个参数?

有一个问题, 构造方法我们明明只定义了一个参数, 为什么生成的构造方法是三个参数呢?

从 Enum 类中我们可以看到, 为每个枚举都定义了两个属性, name 和 ordinal, name 表示我们定义的枚举常量的名称, 如 ADD, SUBTRACT 等, 而 ordinal 是一个顺序号, 根据定义的顺序分别赋予一个整形值, 从 0 开始. 在枚举常量初始化时, 会自动为初始化这两个字段, 设置相应的值, 所以才在构造方法中添加了两个参数. 即:

com.mikan.Operator$1(String name, int ordinal, String operator);

FROM:https://blog.csdn.net/mhmyqn/article/details/48087247

rainbow

这个人很懒,什么都没留下

文章评论