java枚举到底是什么鬼?

枚举类型是什么呢,其实是指一组固定的常量组成合法值的类型。
java中如何定义,看下面代码:

public enum EnumDemo {
    A, B
}

这就是枚举类型。我们知道,java面向对象的语言,不就是对象和类吗,这enum是什么东西?其实这是java语法,是编译器优化,看下面,javap后的汇编:

public final class com.common.EnumDemo extends java.lang.Enum<com.common.EnumDemo> {
  public static final com.common.EnumDemo A;         //2个本类的实例,并且是静态final域

  public static final com.common.EnumDemo B;

  static {};
    Code:
       0: new           #1                  // class com/common/EnumDemo
       3: dup           
       4: ldc           #13                 // String A
       6: iconst_0                          //下面是调用父类构造方法进行初始化
       7: invokespecial #14                 // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #18                 // Field A:Lcom/common/EnumDemo;//赋值给静态域A
      13: new           #1                  // class com/common/EnumDemo  下面同样赋值静态域B
      16: dup           
      17: ldc           #20                 // String B
      19: iconst_1      
      20: invokespecial #14                 // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #21                 // Field B:Lcom/common/EnumDemo;
      26: iconst_2                           //常量2入栈,实例化数组
      27: anewarray     #1                  // class com/common/EnumDemo
      30: dup           
      31: iconst_0      
      32: getstatic     #18                 // Field A:Lcom/common/EnumDemo;
      35: aastore                           //把A赋值给数组第一个元素,下面的是赋值个第二个元素
      36: dup           
      37: iconst_1      
      38: getstatic     #21                 // Field B:Lcom/common/EnumDemo;
      41: aastore       
      42: putstatic     #23                 // Field ENUM$VALUES:[Lcom/common/EnumDemo;
      45: return        

public static com.common.EnumDemo[] values(); //此方法是获取静态代码块中生成的枚举类型数组
    Code:
       0: getstatic     #23                 // Field ENUM$VALUES:[Lcom/common/EnumDemo;
       3: dup           
       4: astore_0      
       5: iconst_0      
       6: aload_0       
       7: arraylength   
       8: dup           
       9: istore_1      
      10: anewarray     #1                  // class com/common/EnumDemo
      13: dup           
      14: astore_2      
      15: iconst_0      
      16: iload_1       
      17: invokestatic  #31                 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
      20: aload_2       
      21: areturn       

  public static com.common.EnumDemo valueOf(java.lang.String);
    Code:
       0: ldc           #1                  // class com/common/EnumDemo
       2: aload_0       
       3: invokestatic  #39                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #1                  // class com/common/EnumDemo
       9: areturn       
}

发现没,其实枚举也是类,并且还继承了java.lang.Enum。由汇编可以看出,枚举的初始化过程是在静态代码块中进行,我们知道,静态代码块只在类首次加载的时候执行一次,final域保证引用地址不会改变。同时,我们也没有看到有公有的构造方法,客户端也就不能创建新的实例,由此可见,枚举类型具有实例受限的特性。
实例受限,很容易让我们想到一种设计模式。没错,就是单例。接下来我们我如何用枚举实现单例。

public enum EnumDemo {
    A;
    public void doSomeThing() {
        System.out.println("dosomething");
    }

    public static void main(String[] args) {
        EnumDemo.A.doSomeThing();
    }
}

看代码,就是这么简单,实例唯一,就是单例,什么线程安全,什么双重检验,什么懒汉饿汉模式,都不用考虑,枚举天然的适合做为单例。这也是Effective Java推崇的做法。
可能有些人用枚举来表示状态,但是需要用数字表示,好存入数据库,这个也简单,只需要为这个类加个属性就ok了,看代码。

public enum EnumDemo {
    A(2), B(4);

    private int status;

    private EnumDemo(int status) {
        this.status = status;
    }

    public int getStatus() {
        return status;
    }

    public static void main(String[] args) {
        System.out.println(EnumDemo.A.getStatus());
        System.out.println(EnumDemo.B.getStatus());
    }
}

运行,打印

2
4

由此可见,用枚举来做常量,会非常直观,也非常的安全,因为有类型安全校验的保证,不会如同int类型的枚举一样,随便一个数字都能进行常量替换。这种怪异的写法,确实不好理解,尤其是有额外的属性后,这就需要熟能生巧了,自己javap慢慢研究。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值