枚举变量是一组具名的值得有限集合,可以直接使用这些值,但是需要加类名前缀(静态导入就不用),它也是一个类,不过不能被继承。可以直接使用等号比较值是否相等,其使用switch语句。例子:
public enum Season
{
//枚举变量和对自身的描述
SPRINNG("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天");
private String description;
private Season(String des){description=des;}//私有构造器,对齐访问没有变
public String getDescription(){return description;}
public static void main(String[] args){
for(Season season:Season.values()){//values由编译器添加的static方法
//比较顺序先后
System.out.println(season.compareTo(Season.FALL));
//返回从0开始的枚举变量的顺序
System.out.println(season+" ordinal: "+season.ordinal());
System.out.println(season.getDeclaringClass()+": "+season.getDescription());
System.out.println(season==Season.FALL);//直接判断是否相等
System.out.println("--------------------");
}
//通过valueOf构建枚举常量
for(String s:"SPRINNG,SUMMER,FALL,WINTER".split(",")){
Season season=Season.valueOf(Season.class,s);
System.out.println(season);
}
}
}
上述代码中values()
是编译器添加的代码,如果将enum
向上转型,那么values()
就不能访问到,我们可以通过Class
的getEnumConstants()
访问所有enum实例。
由于所有的enum对象都继承自java.lang.Enum<E extends Enum<E>>
类,所以enum
类我们只能实现接口,不能继承其他的类了,我们有这么一个例子“枚举所有的食物,给所有的食物分类,然后这些食物又属于枚举类Food”,我们可以如下编写:
interface Food
{
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,TEA,HERB_TEA
}
enum Dessert implements Food{
FRUIT,GELATO,TIRAMISU
}
enum Appetizer implements Food{
SALAD,SOUP,SPRING_ROLLS
}
}
当然如果Food类型比较多的时候,我们也可以使用枚举类的枚举类(类似组合或组装),用Class初始化。如:enum Course{APPETIZER(Food.Appetizer.class);};
EnumSet:采用位标记的高效的不重复集合,所有的元素来自一个enum
EnumMap:采用数组实现的高效Map,所有的元素都来自一个enum,enum实例只能作为键值。比常量相关的方法好,也可以实现 多路分发。
我们可以实现enum实例方法,但是必须要有一个抽象方法(当然我们也可以覆盖实例方法),然后对每一个enum实例实现该方法,如下:
public enum Season
{
//类似一个类,编译出来一个class,但不能作为一个类型来使用
SPRINNG{String getInfo(){return "春天";}},
SUMMER{String getInfo(){return "夏天";}},
FALL{String getInfo(){return "秋天";}},
WINTER{String getInfo(){return "冬天";}
String say(){return "冻死哥哥了";}//方法覆盖
};
abstract String getInfo();//必须要有这个抽象方法
String say(){return "天气不错";}
public static void main(String[] args){
for(Season season:Season.values()){
System.out.println(season.getInfo()+": "+season.say());
}
}
}
enum可以用来实现责任链,按照所有可能的处理方式尝试处理,如果不行就判定不可解。
**多路分发:**在方法调用的时候我们有可能产生多态,产生多态的话就进行分发,多次调用有产生多次多态就就行多次分发,也成为多路分发。还可以用EnumMap或者数组实现分发,一般数组是最直接的方法,只要数据量不大一般都采用数组来实现好。