目录
一、为何引入枚举类型(为了替代魔法值)
什么是魔法值?魔法值有哪些隐患,见另一篇文章编码规约之使用Enum枚举类替代魔法值
那么为什么不用静态变量来替换魔法值呢?
有时候,变量的取值只在一个有限的集合内。例如一年中只有春、夏、秋、冬四季,销售服装只有小、中、大、特大四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或者S、M、L、X。可能,我们有疑问,为何不用静态全局常量来替代呢?以一年四季为例
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_FALL = 3;
public static final int SEASON_WINTER = 4;
但是这样存在着一定的隐患
1.静态常量类型不安全
若一个方法中要求传入季节这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象。
currentSeason.setSeason(需要传入一个整型参数,即季节编码);
currentSeason.setSeason(SEASON_SPRING);//传入春季整型编码
//那既然setSeason接收一个整型数据,那么我就可以向其传入其他整型数据
currentSeason.setSeason(0);
//那么此处的0,又代表什么呢?
2. 没有命名空间
开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代表季节。
二、枚举类型初识
先看一个简单的枚举类
public enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}
1.enum和class、interface的地位一样
2.比较同一枚举类中不同值直接= =
因为枚举类型的值是固定的,不需要发生改变,在比较两个不同值时可以直接使用"= ="就可以了
3.默认继承了java.lang.Enum
enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类。但是,Enum是继承了Object类。枚举类可以实现一个或多个接口
4.所有实例都必须放在第一行展示
枚举类的所有实例都必须放在第一行展示,不需使用new 关键字,不需显式调用构造器。自动添加public static final修饰。
5.不可以被继承
使用enum定义、非抽象的枚举类默认使用final修饰,不可以被继承
6.构造器只能是私有的
因为枚举类型的值是固定的,不需要发生改变,因此枚举被设计成是单例模式。即枚举类型会由JVM在加载的时候,实例化枚举对象,你在枚举类中定义了多少个就会实例化多少个,JVM为了保证每一个枚举类元素的唯一实例,是不会允许外部进行new的,所以会把构造函数设计成private,防止用户生成实例,破坏唯一性。
三、枚举类添加属性和构造器
枚举类内也可以定义属性和方法,可是是静态的和非静态的。但是,构造器一定是私有的,前面已经说过了,枚举类型被设计成了单例模式。构造器需定义成私有的,这样就不能在别处申明此类的对象了。它的Field不应该被改变,这样会更安全,而且代码更加简洁。所以我们将Field用private final修饰。
实际上在第一行写枚举类实例的时候,默认是调用了构造器,所以此处需要传入参数,因为没有显式申明无参构造器,只能调用有参数的构造器。
public enum SeasonEnum {
SPRING("1","春天"),SUMMER("2","夏天"),FALL("3","秋天"),WINTER("4","冬天");
private final int code;
private final String name;
private SeasonEnum(int code,String name)
{
this.code= code;
this.name = name;
}
public String getName() {
return name;
}
public String getCode() {
return code;
}
}
四、枚举类实现接口
枚举类可以实现一个或多个接口。与普通类一样,实现接口的时候需要实现接口中定义的所有方法,若没有完全实现,那这个枚举类就是抽象的,只是不需显式加上abstract修饰,系统化会默认加上。
public enum Operation {
PLUS{
@Override
public double eval(double x, double y) {
return x + y;
}
},
MINUS{
@Override
public double eval(double x, double y) {
return x - y;
}
},
TIMES{
@Override
public double eval(double x, double y) {
return x * y;
}
},
DIVIDE{
@Override
public double eval(double x, double y) {
return x / y;
}
};
/**
* 抽象方法,由不同的枚举值提供不同的实现。
* @param x
* @param y
* @return
*/
public abstract double eval(double x, double y);
}
五、其他API
1. 返回指定名称和指定类的某个枚举类
static Enum valueOf(Class enumClass, String name)
2.返回枚举常量名
String toString()
3.返回枚举常量的序数
int ordinal()
4.返回枚举的所有值
static T[] values()