1.1 关键字enum可以将一组具名的值的优先级和创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。
1.2 基本enum特性
声明一个enum的基本方法:
enum Shrubbery { GROUND, CRAWLING, HANGING }对这个enum进行遍历:
for(Shrubbery s : Shrubbery.values()) { System.out.println(s); System.out.println(s.ordinal());//得到此枚举在enum实例中声明的次序 }
我们还可以以类的形式声明enum,形如:
public enum Spiciness { FIRST, SECOND, THIRD }对于此种enum类来说,除了不能继承自另一个enum类的限制(因为所以的enum都默认继承自Enum,Java中不允许多重继承,所以不能继承)之外,和普通类没有太多区别。在这个类中,你可以编写数组这个类的方法,甚至是main()函数。但是要注意书写的顺序,必须先进行枚举类型的声明,然后再对函数进行声明和定义:
package com.canglingye_19; public enum WithText { //每一个枚举值来说,可以视之为单独的WithText,在后文中,我们将会定义其含参构造函数, //“我是第一个”即为传入构造函数的参数,这样做的好处是,我们可以自己为各个枚举值提供描述,使程序清晰易读 FIRST("我是第一个"), SECOND("我是第二个"); private String description; //构造器为私有访问或者包访问不难理解,因为当我们结束WithText的定义时,我们已经不能够 //再次想WithText中追加枚举值了,故此构造函数不能为public,只能为private或者包访问权限。 private WithText(String des) { this.description = des; } public String getDes() { return description; } //如果不想自己再重新写构造函数,但是又想使对每一个枚举值有单独的描述,则可以覆盖toString()方法 public String toString() { String n = this.name(); String re = new String("可以根据name的不同创建不同的说明"); return re; } public static void main(String[] args) { System.out.println(WithText.FIRST.getDes()); } }
因为java中的switch只支持int和char,如果没有枚举类型,那么你只能case 1: break; case 2: break;时间长了你可能会混淆每个数字所代表的含义,但是,自从有了枚举类型,你得到的解放。用枚举类来替代每个数字,提高程序的可读性。
1.5 enum类型虽然不能够继承自其它基类,但是可以实现其它接口,诸如:
enum ColorGenerator implements Generator<ColorGenerator> { BLUE,BLACK,WHITE,GREEN,YELLOW,RED; private Random rn = new Random(47); public ColorGenerator next() { return this.values()[rn.nextInt(this.values().length)]; } }基于此,当我们要管理比较复杂的接口时,比如一个枚举大类为Food,Food又可以细化分为A,B两种类型,那我们可以用一下这种方式实现此枚举模型:
interface Food { enum A implements Food { A1,A2,A3,A4 } enum B implements Food { B1,B2,B3,B4 } }在上一段代码中,A和B都实现了接口Food,故都可以向上转型为Food,都属于Food类型。但是如果枚举类型更加复杂,我们可以通过下面这种巧妙的方式再次组织枚举:
enum MatureEnum { TrueA(Food.A.class), TrueB(Food.B.class); private Food[] con; private MatureEnum(Class<? extends Food> kind) { con = kind.getEnumConstants(); } public Food getnext() { return con[new Random(47).nextInt(con.length)]; } }这样看起来,代码是否变得更加优雅?整个封装的过程类似于:枚举——接口——枚举
1.6 关于使用EnumSet和EnumMap的技巧
EnumSet属于专门为Enum设计的高效的枚举集合器,其内部默认使用一个long类型作为基础,每一个bit作为一个枚举值,故其可以实现快速的查找等操作。其基本操作如下:
EnumSet<Food.A> test = EnumSet.noneOf(Food.A.class); System.out.println(test); test.add(Food.A.A1); System.out.println(test); test.addAll(EnumSet.of(Food.A.A1,Food.A.A2)); System.out.println(test);
1.7 常量相关的方法
enum Shrubbery { GROUND { String getInfo() { return "有趣"; } }, CRAWLING { String getInfo() { return "哈哈"; } }, HANGING { String getInfo() { return "可以这样"; } }; //在这里声明一个abstract方法,然后强制每个枚举值都实现这个方法 //通过此种方式,可以实现每个枚举值的差异化,当然,通过改写构造函数 //可以实现类似的效果 abstract String getInfo(); }通过定义常量相关方法,可以使每个枚举值变得更具有特色化,当然,也可以通过前文已经介绍的改写构造函数、编写新的函数等方法来实现此种效果。此种方式称之为:表驱动的代码
如果String getInfo()方法不是abstract,而是常量方法,也同样可以覆盖,不过一般来说,推荐使用abstract修饰。
1.8 关于enum实现职责链和状态机的问题,属于设计模式的问题,第二遍学习。
1.9 关于多路分发问题,第二遍学习。
总之,enum枚举类型还是挺有意思的,嘿嘿。