参考
张孝祥系列教程
《thinking in java》- bruce eckel
场景
为什么需要枚举?从 程序中如何表示星期说起!在实际开发中,当然可以在专门的常量类,比如说在Constants.java 中定义常量:public static final int MON = 1 , public static final int TUS = 2 等。但是这么做一点都不面向对象,也容易导致Constants.java类膨胀:系统中要定义常量的地方好多啊:业务异常码,响应字段等等。
分析
把上面的问题稍加抽象一下:我们需要这样一种数据结构 - 只取‘若干个’有限的含义明确的值(比如说,对于星期这样的业务就只能取 MON,TUS,,,SUN 等7个值),若取其他值则编译器最好就报错。在这种广泛存在的业务需求下,“枚举”类型诞生了!实验
- 普通类模拟枚举的实现
package cool.pengych.java.enumtest;
/**
* Simulate the implementation of ENUM
* fun: 普通类模拟枚举的实现
* 1、私有化构造方法-保证实例个数为‘若干个’-有限
* 2、定义所需要的类型常量
* 3、定义常用方法
*
* @author pengych.cool
*/
public class Weekend
{
public static final Weekend MON= new Weekend();
public static final Weekend TUS= new Weekend();
private Weekend(){} // private constructor
/**
* get the next day
* @return Weekend
*/
public Weekend next()
{
if(this.equals(MON)) //if判断,扩展性显然不高:下面会用模板设计模式加以优化
{
return TUS;
}
return MON;
}
public String toString()
{
return this.equals(MON) ? "MON" :"TUS";
}
public static void main(String[] args)
{
System.out.print(WeekendNicer.MON.next());
}
}
优化后的代码
package cool.pengych.java.enumtest;
/**
* optimize the implementation of ENUM with
* 利用模板方法设计模式优化Weekend.java类,使代码更加模块化,增强可扩展性
* @author pengych.cool
*/
public abstract class WeekendNicer
{
public abstract WeekendNicer next();
private WeekendNicer(){}
public static final WeekendNicer MON = new WeekendNicer()
{
public WeekendNicer next()
{
return TUS;
}
};
public static final WeekendNicer TUS = new WeekendNicer()
{
public WeekendNicer next()
{
return MON;
}
};
public String toString()
{
return this.equals(MON) ? "MON" :"TUS";
}
}
- 枚举的初体验与进阶实战
package cool.pengych.java.enumtest;
/**
* 枚举类实战
*
* @author pengych.cool
*/
public class EnumTest
{
public static void main(String[] args)
{
Weekend weekend = Weekend.MON;
System.out.println(weekend);
WeekendE weekende = WeekendE.MON;
System.out.println(weekende.name());
System.out.println(weekende.ordinal());
System.out.println(WeekendE.valueOf("SUN").toString());
System.out.println(WeekendE.values().length);
}
/**
* base enum : 枚举类基本使用
*/
public enum WeekendE
{
MON(2),TUS,THI,FRI,WES,SAT,SUN;
private WeekendE(){System.out.println("constructor with no argument!");}
private WeekendE(int day){System.out.println("constructor with argument!");}
}
/**
* enhance enum : 枚举类进阶
*/
public enum TrafficLamp
{
RED(10) // 匿名内部类(调用父类的带参构造方法)
{
public TrafficLamp nextLamp()
{
return YELLOW;
}
},
YELLOW()
{
public TrafficLamp nextLamp()
{
return RED;
}
},
GREEN(45)
{
public TrafficLamp nextLamp()
{
return YELLOW;
}
};
private int time;
private TrafficLamp(){}
private TrafficLamp(int time)
{
this.time = time;
}
public abstract TrafficLamp nextLamp();
}
}
- 单常量枚举简化单例模式的实现
package cool.pengych.java.enumtest;
/**
* 由枚举类的实现原理可知,枚举类中若只有一个枚举常量,则该常量就是这个枚举类的唯一实例
* @author pengych.cool
*
*/
public enum EnumSingleton
{
LOG;
public void error(String log)
{
System.out.println(log);
}
public void debug(String log)
{
System.out.println(log);
}
public static void main(String[] args)
{
LOG.debug("test enum sigleton ");
LOG.error("test enum sigleton ");
}
}
总结
package cool.pengych.java.enumtest;
/**
* 由枚举类的实现原理可知,枚举类中若只有一个枚举常量,则该常量就是这个枚举类的唯一实例
* @author pengych.cool
*
*/
public enum EnumSingleton
{
LOG;
public void error(String log)
{
System.out.println(log);
}
public void debug(String log)
{
System.out.println(log);
}
public static void main(String[] args)
{
LOG.debug("test enum sigleton ");
LOG.error("test enum sigleton ");
}
}
在实际项目中,遇到类型有限的业务性强的数据表示,优先考虑枚举类。