一.枚举类型的基础知识
1.1枚举类型的简单实现
enum Size{SMALL,MIDDLE,BIG}
1.2枚举类型的常用方法
1.2.1一般方法
打箭头的就是常用的一般方法,其中valueOf()方法会在编译器重载一次
1.2.2特殊的方法
枚举类型有两个比较特殊的静态方法 1.values() 2.valueOf(String s)
其中,valueOf(String s)方法相比于上图中的valueOf()方法更加简便一点,返回枚举类型的具体实例
values()方法则会返回此枚举类型的数组
for(Size size : Size.values()) { System.out.println("size : " + size); }
但是,因为values()是编译器加入的,所以将美枚举类型实例向上转型后,不可再用values(),解决办法如下:
for(Size size :Size.class.getEnumConstants()) { System.out.println("size : " + size); }
调用类字面常量的getEnumConstants()可以解决这个问题,非类字面常量调用则返回null
1.3枚举类型的进一步扩充
枚举类型本身是不可继承的,除此之外,他与一般的类并没有太大的区别
enum Size{ SMALL(1),MIDDLE(2),BIG;//枚举类型的具体实例,调用构造方法 int i;//可以拥有变量 Size(){//可以有构造方法 this.i = 0; } Size(int i){//方法可以重载 this.i = i; } public void info() {//普通方法 System.out.println(i); } public static void main(String[] args) {//甚至可以有main方法 } }
还可以实现类似多态的行为
enum Size{ //枚举类型的具体实例,可以调用构造方法,也可以重写抽象方法和一般方法(可选) SMALL(1){ void print() { System.out.println(this.name() + i); } public void getI() { System.out.println("重写后的i=" + i); } }, MIDDLE(2){ void print() { System.out.print("xxxxxxxxx"); } }, BIG{ void print() { i = i + 1; } }; int i;//可以拥有变量 Size(){//可以有构造方法 this.i = 0; } Size(int i){//方法可以重载 this.i = i; } public void info() {//普通方法 System.out.println(i); } public static void main(String[] args) {//甚至可以有main方法 } abstract void print();//具体的枚举实例会进行重写,不同的实例调用方法会有不同的行为 public void getI() {//一般的方法可以选择性的重写 System.out.println("i = " + i); } }
二.枚举类型的分类管理
2.1利用接口组织枚举类型
public interface Food { enum Appetizer implements Food { SALAD, SOUP, SPRING_ROLLS; } enum MainCourse implements Food { LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO; } enum Dessert implements Food { TIRAMISU, GELATO, BLACK_FOREST_CAKE, FRUIT, CREME_CARAMEL; } enum Coffee implements Food { BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, LATTE, CAPPUCCINO, TEA, HERB_TEA; } }
这样便可以将所有的枚举类型的实例向上转型为同一类型
2.2利用接口+枚举实现枚举的枚举
public enum Course { APPETIZER(Food.Appetizer.class), MAINCOURSE(Food.MainCourse.class), DESSERT(Food.Dessert.class), COFFEE(Food.Coffee.class); private Food[] values; private Course(Class<? extends Food> kind) { values = kind.getEnumConstants(); } }2.3重新组织以上两段代码,得到更好的组织方式,更好理解代码
public enum Meal2 { APPETIZER(Food.Appetizer.class), MAINCOURSE(Food.MainCourse.class), DESSERT(Food.Dessert.class), COFFEE(Food.Coffee.class); private Food[] values; private Meal2(Class<? extends Food> kind) { values = kind.getEnumConstants(); } public interface Food { enum Appetizer implements Food { SALAD, SOUP, SPRING_ROLLS; } enum MainCourse implements Food { LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO; } enum Dessert implements Food { TIRAMISU, GELATO, BLACK_FOREST_CAKE, FRUIT, CREME_CARAMEL; } enum Coffee implements Food { BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, LATTE, CAPPUCCINO, TEA, HERB_TEA; } } }
三.枚举类型的应用
3.1单例模式
我的另一篇关于单例模式的文章------点击打开链接
3.2职责链模式
3.3状态机
3.4多路分发
Java本身只支持单路分发,即当下要执行的操作含有两个类型未知的对象是,Java虚拟机只能判定其中一个对象的具体类型,
而双路分发则可以实现两个位置类型的对象自己交流,而不用我们自己去判断其中一个对象的类型。多路分发依此类推。
enum Outcome{WIN,LOSE,DRAW}//模拟石头剪刀布的结果 public enum RoShamBo implements someInterface{//将具体实例向上转型为实现的接口 PAPER(DRAW, LOSE, WIN),//预先得到比赛的结果,然后放在本地变量中,顺序有要求 SCISSORS(WIN, DRAW, LOSE), ROCK(LOSE, WIN, DRAW); private Outcome vPAPER, vSCISSORS, vROCK; RoShamBo(Outcome paper,Outcome scissors,Outcome rock) { this.vPAPER = paper; this.vSCISSORS = scissors; this.vROCK = rock; } public Outcome compete(RoShamBo it) {//调用compete方法实现第一次分发 switch(it) {//switch实现第二次分发 default: case PAPER: return vPAPER; case SCISSORS: return vSCISSORS; case ROCK: return vROCK; } } }
四.枚举类型的小知识点
4.1静态导入
枚举类型的使用可以不写类名
import static package.Enum.*//package是包名,Enum是枚举类型
4.2和switch配合使用也可以不写枚举名
4.3有两个相关的数据结构,EnumSet,EnumMap