枚举类型是Java1.5中新增的特性,它是一种特殊的数据类型。之所以特殊是因为它既是一种类类型(class)却又比类类型多了些特殊的约束,但这些约束的存在也造就了枚举类型的简洁性、安全性和便捷性。
public class EnumDemo {
public static void main(String[] args) {
Season spring = Season.SPRING;
System.out.println(spring);
}
}
enum Season{
SPRING, SUMMER, FALL, WINTER;
}
在第一行写枚举类的实例的时候,默认调用了构造器,如果使用的不是默认的无参构造,就要创建有参构造
构造器需要定义成私有的,枚举类通常设计成不可变类,它的Filed属性不应该被改变,这样会更加安全,代码更加简洁
在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类,也就是说通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。
这个类长这个样子
final class Day extends Enum
{
//编译器为我们添加的静态的values()方法
public static Day[] values()
{
return (Day[])$VALUES.clone();
}
//编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
public static Day valueOf(String s)
{
return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
}
//私有构造函数
private Day(String s, int i)
{
super(s, i);
}
//前面定义的7种枚举实例
public static final Day MONDAY;
public static final Day TUESDAY;
public static final Day WEDNESDAY;
public static final Day THURSDAY;
public static final Day FRIDAY;
public static final Day SATURDAY;
public static final Day SUNDAY;
private static final Day $VALUES[];
static
{
//实例化枚举实例
MONDAY = new Day("MONDAY", 0);
TUESDAY = new Day("TUESDAY", 1);
WEDNESDAY = new Day("WEDNESDAY", 2);
THURSDAY = new Day("THURSDAY", 3);
FRIDAY = new Day("FRIDAY", 4);
SATURDAY = new Day("SATURDAY", 5);
SUNDAY = new Day("SUNDAY", 6);
$VALUES = (new Day[] {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
});
}
}
从上面反编译得来的代码可以发现:(这代码是copy过来的)
Enum类中的常用方法:
enum Season implements Info{
SPRING("春天"),
SUMMER("夏天"),
FALL("秋天"),
WINTER("冬天");
private String desc;
//将构造函数私有化
private Season(String desc){
this.desc = desc;
}
public String getDesc() {
return desc;
}
与常规抽象类一样,enum类允许我们为其定义抽象方法,然后使每个枚举实例都实现该方法,以便产生不同的行为方式,注意abstract关键字对于枚举类来说并不是必须的如下:
enum Season implements Info{
SPRING("春天"){
@Override
public String getInfo() {
return info();
}
@Override
public String info() {
return "春天有点儿绿";
}
},
SUMMER("夏天"){
@Override
public String getInfo() {
return info();
}
@Override
public String info() {
return "夏天有点儿热";
}
},
FALL("秋天"){
@Override
public String getInfo() {
return info();
}
@Override
public String info() {
return "秋天有点儿黄";
}
},
WINTER("冬天") {
@Override
public String getInfo() {
return info();
}
@Override
public String info() {
return "冬天有点儿冷";
}
};
private String desc;
private Season(String desc){
this.desc = desc;
}
public String getDesc() {
return desc;
}
public abstract String getInfo();
}
使用switch进行条件判断时,条件参数一般只能是整型,字符型。而枚举型确实也被switch所支持,在java 1.7后switch也对字符串进行了支持。
单例模式可以说是最常使用的设计模式了,它的作用是确保某个类只有一个实例,自行实例化并向整个系统提供这个实例。在实际应用中,线程池、缓存、日志对象、对话框对象常被设计成单例,总之,选择单例模式就是为了避免不一致状态。
关于单例,我们总是应该记住:保证线程安全,延迟加载,序列化与反序列化安全,反射安全是很重要的。
枚举单例的实现
//非常简单,你想加什么代码自己看着办
public enum Singleton {
INSTANCE;
}
代码相当简洁,我们也可以像常规类一样编写enum类,为其添加变量和方法,访问方式也更简单,使用SingletonEnum.INSTANCE进行访问,这样也就避免调用getInstance方法,更重要的是使用枚举单例的写法,我们完全不用考虑序列化和反射的问题。枚举序列化是由jvm保证的,每一个枚举类型和定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定:在序列化时Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的,并禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,从而保证了枚举实例的唯一性。
原文:https://www.cnblogs.com/codeloong/p/14839066.html