[关闭]
@ghimi 2018-10-06T15:46:28.000000Z 字数 2846 阅读 890

Java基础-枚举详解

Java 枚举


前言

反编译那些事-枚举的反编译
Java枚举与常量类的区别

1. 历史

枚举是JDK1.5 版本新增的特性(泛型,foreach等如今被广泛应用的特性也是有JDK1.5时所新增的),另外到了JDK1.6后switch语句支持枚举类型.

2.枚举的语法解析

示例:

  1. public enum ColorEnum{
  2. RED,BLUE,GREEN
  3. }

通过工具解析后class后获得的源代码(工具参考上面的链接)

  1. public final class ColorEnum extends Enum {
  2. // 返回存储枚举实例的数组的副本.values()方法通常用于foreach循环遍历枚举常量
  3. public static ColorEnum[] values(){
  4. return (ColorEnum[])$VALUES.clone();
  5. }
  6. //根据实例名获取实例
  7. public static ColorEnum valueOf(String s){
  8. return (ColorEnum)Enum.valueOf(ColorEnum,s);
  9. }
  10. // 私有构造方法,这里调用了父类的构造方法,其中参数s对应了常量名,参数i代表枚举的一个顺序(这个顺序与枚举的声明顺序对应,用于oridinal()方法返回顺序值)
  11. private ColorEnum(String s,int i){
  12. super(s,i)
  13. }
  14. // 我们定义的枚举在这里声明了三个 ColorEnum的常量对象引用对象的实例化在static静态块中
  15. public static final ColorEnum RED;
  16. public static final ColorEnum BLUE;
  17. public static final ColorEnum GREEN;
  18. //将所有枚举的实例存放在数组中
  19. private stataic final ColorEnum $VALUES[];
  20. static {
  21. RED = new ColorEnum("RED",0);
  22. BLUE = new ColorEnum("BLUE",1);
  23. GREEN = new ColorEnum("GREEN",2);
  24. // 将所有枚举的实例存放在数组中
  25. $VALUES = (new ColorEnum[]{
  26. RED,BLUE,GREEN
  27. });
  28. }
  29. }

现在我们在枚举类中增加自己的字段以及一些辅助方法,代码如下:

  1. public enum ColorEnum {
  2. RED("red","红色"),GREEN("green","绿色"),BLUE("blue","蓝色");
  3. // 防止字段值被修改,增加的字段也统一final表示常量
  4. private final String key;
  5. private final String value;
  6. private ColorEnum(String key,String value){
  7. this.key = key;
  8. this.value = value;
  9. }
  10. // 根据 key 获取枚举
  11. public static ColoeEnum getEnumByKey(String key){
  12. if(null == key){
  13. return null;
  14. }
  15. for(ColorEnum temp:ColorEnum.values()){
  16. if(temp.getKey.equals(key)){
  17. return temp;
  18. }
  19. }
  20. }
  21. public String getKey(){
  22. return key;
  23. }
  24. public String getValue(){
  25. return value;
  26. }
  27. }

反编译的结果:

  1. public final class ColorEnum extends Enum
  2. {
  3. public static ColorEnum[] values()
  4. {
  5. return (ColorEnum[])$VALUES.clone();
  6. }
  7. public static ColorEnum valueOf(String s)
  8. {
  9. return (ColorEnum)Enum.valueOf(ColorEnum, s);
  10. }
  11. //构造方法在原基础上加上我们新增的两个形参
  12. private ColorEnum(String s, int i, String s1, String s2)
  13. {
  14. super(s, i);
  15. key = s1;
  16. value = s2;
  17. }
  18. //自定义方法,通过key值获得对应的枚举对象
  19. public static ColorEnum getEnumByKey(String s)
  20. {
  21. if(null == s)
  22. return null;
  23. ColorEnum acolorenum[] = values();
  24. int i = acolorenum.length;
  25. for(int j = 0; j < i; j++)
  26. {
  27. ColorEnum colorenum = acolorenum[j];
  28. if(colorenum.getKey().equals(s))
  29. return colorenum;
  30. }
  31. return null;
  32. }
  33. public String getKey()
  34. {
  35. return key;
  36. }
  37. public String getValue()
  38. {
  39. return value;
  40. }
  41. public static final ColorEnum RED;
  42. public static final ColorEnum GREEN;
  43. public static final ColorEnum BLUE;
  44. //我们自定义的两个字段
  45. private final String key;
  46. private final String value;
  47. private static final ColorEnum $VALUES[];
  48. static
  49. {
  50. RED = new ColorEnum("RED", 0, "red", "\u7EFE\u3223\u58CA");
  51. GREEN = new ColorEnum("GREEN", 1, "green", "\u7F01\u80EF\u58CA");
  52. BLUE = new ColorEnum("BLUE", 2, "blue", "\u9483\u6FCA\u58CA");
  53. $VALUES = (new ColorEnum[] {
  54. RED, GREEN, BLUE
  55. });
  56. }
  57. }

枚举的好处以及与常量类的区别

  1. 枚举型可以直接和数据库打交道,我通常使用varchar类型存储,对应的是枚举的常量名.数据库中好像也有枚举类型,不过没试过)
  2. switch语句支持枚举型,当switch使用int,String类型时,由于值的不稳定型往往会有越界的现象,对于这个的处理往往只能通过if条件筛选以及default模块来处理.而使用枚举型后,在编译期间限定类型,不允许发生越界的情况.
  3. 当你使用常量类时,往往得通过equals去判断两者是否相等,使用枚举的话由于常量地址唯一,可以用==直接对比,性能会有提高.
  4. 常量类编译时,是直接把常量的值编译到类的二进制代码里,常量的值在升级中变化后,需要重新编译引用常量的类,因为里面存的是旧值.枚举类编译时,没有把常量值编译到代码里,及时常量的值发生变化,也不会影响引用常量的类.
  5. 枚举类编译后默认为final class ,不允许继承可防止子类被修改.常量类可被继承修改,增加字段等,容易导致父类的不兼容.
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注