java枚举类型

咸鱼了好几天,恢复一下更新

看到一本书介绍单例模型时使用了enum,非常好奇,平时很少使用枚举类型,趁这个机会深入了解一下。

public class EnumDemo {

    public static void main(String[] args){
        //直接引用
        Day day =Day.MONDAY;
    }

}
//定义枚举类型
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

上面是枚举类型的基础用法,就是定义一些值,通过查看class反编译的结果可以看到,jvm帮助我们声明了七个Day对象,即为枚举类型中的那些值。

使用枚举类型实现单例模式

很多时候我们需要控制一个类只能被实例化一次,比如某个窗体。即这个类有singleton属性,一般来说我们可以通过将构造函数private化来解决这个问题,之后可以new一个静态公有成员来访问或者使用get方法来访问。这样子做有一个问题,我们依旧可以通过反射机制来调用这个构造器。

还有一点,序列化可能会破坏单例模式,比较每次反序列化一个序列化的对象实例时都会创建一个新的实例,当然目前的解决方案一般是使用readResolve()这个勾子:

public class Singleton implements java.io.Serializable {     
   public static Singleton INSTANCE = new Singleton();     

   protected Singleton() {     
   }  

   //反序列时直接返回当前INSTANCE
   private Object readResolve() {     
            return INSTANCE;     
      }    
}   

如果使用枚举类型,那么我们可以这么做:

public enum Elvis {
    INSTANCE,INSTANCE2;
    public int a = 0;
    public void leaveTheBuilding() {
        a++;
        System.out.println(a);
    }
}

可以看到,枚举类型完美的满足了我们的要求,绝对的防止多次实例化,也可以面对复杂的序列化问题。

这里摘抄一段来自zejian的博客的介绍

枚举序列化是由jvm保证的,每一个枚举类型和定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定:在序列化时Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的并禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,从而保证了枚举实例的唯一性。

《java枚举类型》上有1条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注