6.2Java枚举基本使用,原理探究和扩展

枚举类型的基本使用

枚举类是和class一样的java关键字,用来定义枚举类的
为什么定义的枚举类,可以单独定义和直接使用,不需要实例化?这需要探究它的内部原理

定义和使用一个枚举

public class enumdemos1 {
    public enum EnumDemo1 {
        A,B,C,D,E
    }

    public static void main(String[] args) {
        EnumDemo1 a = EnumDemo1.A;
        System.out.println(a);
        System.out.println(EnumDemo1.A);
        System.out.println(Arrays.asList(EnumDemo1.values()));
        System.out.println(EnumDemo1.valueOf(String.valueOf(EnumDemo1.B)));
        System.out.println(EnumDemo1.B.ordinal());
    }
}

Enum类的常用方法

values() 以数组形式返回枚举类型的所有成员
valueOf() 将普通字符串转换为枚举实例
compareTo() 比较两个枚举成员在定义时的顺序
ordinal() 获取枚举成员的索引位置

枚举的原理

通过字节码看enum背后执行的操作

public enum EnumDemo1 {
    A,
    B,
    C,
    D;

    private EnumDemo1() {
    }
}
Compiled from "EnumDemo1.java"
public final class src.Temun.EnumDemo1 extends java.lang.Enum<src.Temun.EnumDemo1> {
  public static final src.Temun.EnumDemo1 A;

  public static final src.Temun.EnumDemo1 B;

  public static final src.Temun.EnumDemo1 C;

  public static final src.Temun.EnumDemo1 D;

  public static src.Temun.EnumDemo1[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Lsrc/Temun/EnumDemo1;
       3: invokevirtual #2                  // Method "[Lsrc/Temun/EnumDemo1;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Lsrc/Temun/EnumDemo1;"
       9: areturn

  public static src.Temun.EnumDemo1 valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class src/Temun/EnumDemo1
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #4                  // class src/Temun/EnumDemo1
       9: areturn

  static {};
    Code:
       0: new           #4                  // class src/Temun/EnumDemo1
       3: dup
       4: ldc           #7                  // String A
       6: iconst_0
       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #9                  // Field A:Lsrc/Temun/EnumDemo1;
      13: new           #4                  // class src/Temun/EnumDemo1
      16: dup
      17: ldc           #10                 // String B
      19: iconst_1
      20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #11                 // Field B:Lsrc/Temun/EnumDemo1;
      26: new           #4                  // class src/Temun/EnumDemo1
      29: dup
      30: ldc           #12                 // String C
      32: iconst_2
      33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      36: putstatic     #13                 // Field C:Lsrc/Temun/EnumDemo1;
      39: new           #4                  // class src/Temun/EnumDemo1
      42: dup
      43: ldc           #14                 // String D
      45: iconst_3
      46: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      49: putstatic     #15                 // Field D:Lsrc/Temun/EnumDemo1;
      52: iconst_4
      53: anewarray     #4                  // class src/Temun/EnumDemo1
      56: dup
      57: iconst_0
      58: getstatic     #9                  // Field A:Lsrc/Temun/EnumDemo1;
      61: aastore
      62: dup
      63: iconst_1
      64: getstatic     #11                 // Field B:Lsrc/Temun/EnumDemo1;
      67: aastore
      68: dup
      69: iconst_2
      70: getstatic     #13                 // Field C:Lsrc/Temun/EnumDemo1;
      73: aastore
      74: dup
      75: iconst_3
      76: getstatic     #15                 // Field D:Lsrc/Temun/EnumDemo1;
      79: aastore
      80: putstatic     #1                  // Field $VALUES:[Lsrc/Temun/EnumDemo1;
      83: return
}

从字节码可以看出

  • enum最后被转为继承了extends java.lang.Enum<src.Temun.EnumDemo1>的final不可以继承的类
  • enum生成的类的类名就是枚举类的类名
  • enum里定义的变量A,B,C,D都被实例化为了为了静态的枚举类对象,在static代码块里被初始化,

总结:

  • 枚举类本质上也是一个普通的类,可以里面正常的定义方法和初始化函数等等

  • 而枚举类中定义的成员,比如上面代码里的A,B,C,D其实是这个枚举类实例化的静态对象

    • 因为是静态对象,所以可以直接获取到,又因为实例化了,所以可以调用枚举类内部自定义的方法。
    • 因为对象会被实例化,可以调用定义的初始化函数,而且会把enum类中定义的一些非静态方法转为对象的内部方法,对象在声明的时候也可以自定义自己专属方法
  • 枚举内部会自动生成两个静态的枚举方法(values,valueOf)

    • 枚举的静态方法数据类对象的,通过类直接调用

枚举类就是一个普通的类,不同的是可以直接写几个值用来替代生成这个类的静态对象的过程,因此是一种定义类并在类中实例化静态对象的语法糖

单例模式下使用枚举类型

利用了枚举的对象是静态对象(准确的说应该是:类的静态字段),在jvm的类的静态变量初始化的时候使用了clinit()方法进行了初始化,这个方法是线程安全的

class User {
    //私有化构造函数
    private User(){ }

    //定义一个静态枚举类
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private User user;
        //私有化枚举的构造函数
        private SingletonEnum(){
            user=new User();
        }
        public User getInstnce(){
            return user;
        }
    }

    //对外暴露一个获取User对象的静态方法
    public static User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

public class Test {
    public static void main(String [] args){
        System.out.println(User.getInstance());
        System.out.println(User.getInstance());
        System.out.println(User.getInstance()==User.getInstance());
    }
}

枚举集合EnumMap和EnumSet

枚举集合和普通的集合相同,就是键值k为枚举类型罢了

简单的例子,参考使用即可

public static void main(String[] args) throws Exception {
        EnumMap<Season, String> map = new EnumMap<>(Season.class);
        map.put(Season.FALL, "硕果累累的秋天");
        map.put(Season.WINTER, "寒风凛冽的冬天");
        System.out.println(map.get(Season.FALL));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不被定义的号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值