枚举
背景
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());
}
}