枚举

背景

public class Season {

    public static final Integer SPRING = 1;
    public static final Integer SUMMER = 2;
    public static final String AUTUMN = "3";
    public static final Integer WINTER = 4;

    private Integer type;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public static void main(String[] args) {
        Season season = new Season();
        //1.魔法数字,代码可读性差、易用性低
        season.setType(1);
        //2.用常量传递
        season.setType(Season.SUMMER);
        //但会引入类型、值等相关校验
        season.setType(Season.AUTUMN);//此处Sting无法传递给Integer
        //3.耦合性高,扩展性差
        //当引入其他的参数,那么还需要增加相关校验
        season.setType(Season.ALL);//不利于扩展,需要重新写一套校验
        //4.由于开发员可以直接写常量值, 所以不能用==对比,只能用equals对比,不能优化性能
    }
}

概念

1.在某些情况下,一个类的对象是有限而且固定的,比如季节类,它有春夏秋冬(属于季节类)的四个对象,这种实例有限而且固定的类,在java里称为枚举类
2.枚举是一种规范它规范了参数的形式,这样就可以不用考虑类型的不匹配并且显式的替代了int型参数可能带来的模糊概念 枚举像一个类,又像一个数组。
3.创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。

模拟(自定义)

public class Season {

    private final String name;
    private final String desc;

    public static final Season SPRING = new Season("春天","春光无限");
    public static final Season SUMMER = new Season("夏天","夏日炎炎");
    public static final Season AUTUMN = new Season("秋天","秋高气爽");
    public static final Season WINTER = new Season("冬天","寒冬腊月");

    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
    public String getName() {
        return name;
    }
    public String getDesc() {
        return desc;
    }
    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
    public static void main(String[] args) {
        Season s = Season.SPRING;
        System.out.println("s = " + s);
        //结果
//      s = Season{name='春天', desc='春光无限'}

    }
}

特点

如下:
1.JDK1.5新增enum关键字用于定义枚举类
2.枚举类构造方法必须(默认)是private final修饰
3.若枚举类显示定义了带参数的构造器,那么列举枚举值的时候也必须传入相关参数
4.必须在枚举类的第一行声明枚举类对象
5.使用enum定义的枚举类默认继承的是java.lang.Enum类而非Object
6.所有枚举值都是public , static , final的,public static final若未添加,系统默认会添加
7.枚举类和普通java类一样,可以实现一个或多个接口
8.枚举类的所有实例必须在枚举类中显示列出,否则这个枚举类将永远都不能产生实例,这些枚举值代表了该枚举类的所有可能实例
9.枚举类Enum已经实现了Serializable和Comparable接口,可以序列化和比较
10.Enum覆载了了toString方法,因此我们如果调用Color.Blue.toString()默认返回字符串”Blue”

使用

无参枚举类

	//无参枚举类
	public enum  Season {
	    SPRING,SUMMER,AUTUMN,WINTER //实际调用Season()产生一个Season的实例
	}
	//调用
    private static void test() {
        Season s = Season.AUTUMN;
        switch (s){
            case SPRING:
                System.out.println(Season.SPRING.toString());
                break;
            case AUTUMN:
                System.out.println(Season.AUTUMN.toString());
                break;
            default:
                System.out.println("其他");
        }

    }

枚举

有参枚举类

public enum  Season {

    //必须第一行显示定义,多个枚举值用,分割,最后以;结束
    SPRING("春天","春光无限"),//等同于 public static final Season SPRING = new SPRING("春天","春光无限")
    SUMMER("夏天","夏日炎炎"),
    AUTUMN("秋天","秋高气爽"),
    WINTER("冬天","寒冬腊月");

    private String name;
    private String desc;

    Season() {//定义不接受参数的枚举
    }

    Season(String name) {//定义接收一个参数的枚举
        this.name = name;
    }

    Season(String name, String desc) {//定义接收两个参数的枚举
        this.name = name;
        this.desc = desc;
    }
    //自定义一个方法
    public String getName() {
        return name;
    }
}

private static void test() {
   Season s = Season.AUTUMN;
   switch (s){
       case SPRING:
           System.out.println("这个是 "+ s.getName());
           break;
       case AUTUMN:
           System.out.println("这个是 "+ s.getName());
           break;
       default:
           System.out.println("其他");
   }
}

枚举

方法

枚举

name() tostring() 方法

        Season s = Season.SPRING;
        System.out.println("name:s = " + s.name());
        System.out.println("tostring:s = " + s.toString());

枚举

ordinal() 方法

        Season s1 = Season.SPRING;
        Season s2 = Season.SUMMER;
        Season s3 = Season.AUTUMN;
        System.out.println("s1 = " + s1.ordinal());
        System.out.println("s2 = " + s2.ordinal());
        System.out.println("s3 = " + s3.ordinal());

枚举

values() valueOf()方法

		//1.values():已数组的方式,获取所有的枚举成员
		Season[] seasons = Season.values();
        for(int i = 0;i < seasons.length;i++){
            System.out.println(seasons[i]);
        }
		System.out.println("---------------------");
        //2.valueOf(String name):要求传入的形参name是枚举类对象的名字,获取枚举对象。
        //否则,报java.lang.IllegalArgumentException异常
        String str = "WINTER";
        Season sea = Season.valueOf(str);
        System.out.println("sea = " + sea);

枚举

    private static void test() {
        Season[] seasons = Season.values();
        for(int i = 0;i < seasons.length;i++){
            System.out.println(seasons[i].getName()+"的场景为:"+seasons[i].getDesc());
        }
        System.out.println("---------------------");
    }

枚举

接口实现

public interface Info {
    void show();
}
public enum  Season implements Info{
    SPRING("spring", "春光无限"){//其实这里就是一个内部类
        public void show(){
            System.out.println("春天花会开");
        }
    },
    SUMMER("summer", "夏日炎炎"){
        public void show(){
            System.out.println("夏天裙会飘");
        }
    },
    AUTUMN("autumn", "秋高气爽"){
        public void show(){
            System.out.println("秋天果会熟");
        }
    },
    WINTER("winter", "寒冬腊月"){
        public void show(){
            System.out.println("冬天暖被窝");
        }
    };
    private String name;
    private String desc;

    Season(String name) {//定义接收一个参数的枚举
        this.name = name;
    }

    Season(String name, String desc) {//定义接收两个参数的枚举
        this.name = name;
        this.desc = desc;
    }

}
    private static void test() {
        Season s = Season.AUTUMN;
        switch (s){
            case SPRING:
                s.show();
                break;
            case AUTUMN:
                s.show();
                break;
            default:
                System.out.println("其他");
        }

    }

枚举
枚举

单例

枚举

集合使用

    private static void test() {
        // EnumSet的使用
        EnumSet<Season> weekSet = EnumSet.allOf(Season.class);
        for (Season day : weekSet) {
            System.out.println(day);
        }

        // EnumMap的使用
        EnumMap<Season, String> weekMap = new EnumMap(Season.class);
        weekMap.put(Season.SPRING, "星期一");
        weekMap.put(Season.SUMMER, "星期二");
        for (Iterator<Map.Entry<Season, String>> iter = weekMap.entrySet().iterator(); iter.hasNext();) {
            Map.Entry<Season, String> entry = iter.next();
            System.out.println(entry.getKey().name() + ":" + entry.getValue());
        }
    }

枚举

参考:
java enum(枚举)使用详解 + 总结