枚举概述
枚举从JDK1.5诞生,是一种特殊的类,表示一组固定属性,相当于Enum的语法糖。
在1.5之前,例如要定义一个表示季节,通常做法是定义一组静态变量,代码如下所示:
/**
*
* @author 高波
*/
public class Season{
//定义四个静态常量来表示季节
public static final int SPRING = 1;
public static final int SUMMER= 2;
public static final int AUTOMER = 3;
public static final int WINTER = 4;
}
这样做我们也可以实现具体功能,但是这种做法会存在以下几种问题:
- 类型不安全,每个静态常量都是int类型,换一个角度来说就是一个季节就代表一个整数,整数直接可以进行相互运算,这显然是不可以的,所以存在一定的安全隐患。
- 输出打印的信息不明确,输出Season.SPRING时,这时候显示的1,如果别人阅读这个代码,必须翻阅源码才知道原来1就是SPRING。
从JDK1.5版本,引入一个enum关键字,它和class、interface地位相同,说白了enum其实就是一个特殊的类:
- 枚举类可以实现多个接口,但是不能继承其它任何类,默认继承自
java.lang.Enum
类,此类是一个抽象类,同时也实现了java.io.Serializable
接口和java.lang.Comparable
接口。 - 使用enum定义的类是如果不是抽象类,则自动编译器会使用fianl修饰,因此枚举不可以派生子类。
- 枚举类的构造只能是私有的,如果不声明构造,则系统会提供一个私有的构造。
上面代码我们使用枚举来实现
/**
*
* @author 高波
*/
public class TestSeason{
public static void main(String[] args){
//直接访问即可
Season = Season.SPRING;
}
}
enum Season{
//定义四个枚举
SPRING,SUMMER,AUTUMN,WINTER;
}
这是一个枚举最简单的基本使用,接下来定义一个带有自定义属性和方法的枚举类(虽然它比较特殊,别人有的它当然也不能少):
/**
*
* @author 高波
*/
enum SeasonEnum{
//此处的枚举是通过私有构造方法由系统来创建。
SPRING("春天"),SUMMER("夏天"),AUTUMN("秋天"),WINTER("冬天");
private String seasonName;
private SeasonEnum(String seasonName){
this.seasonName = seasonName;
}
public String getSeasonName() {
return this.seasonName;
}
}
通过反编译看一下SeasonEnum到底做了什么,我是使用idea的View菜单下的Show bytecode实现:
//此处通过反编译可以发现SeasonEnum继承自Enum类
final enum cn/boshao/test/SeasonEnum extends java/lang/Enum {
//定义的四种枚举实例
public final static enum SeasonEnum SPRING;
public final static enum SeasonEnum SUMMER;
public final static enum SeasonEnum AUTUMN;
public final static enum SeasonEnum WINTER;
//私有属性
private String seasonName;
//由java编译器生成
private final static SeasonEnum[] $VALUES;
private SeasonEnum(String seasonName){
this.seasonName = seasonName;
}
//java编译器自动生成的values方法,返回SeasonEnum数组
public static SeasonEnum[] values(){
return (SeasonEnum[])$VALUES.clone();
}
//由java编译器自动生成valueOf()方法,可以理解为Enum.valueOf一种简便用法
public static SeasonEnum valueOf(String str){
return (SeasonEnum)Enum.valueOf(SeasonEnum.class, str);
}
public getSeasonName(){
return this.seasonName;
}
static{
SPRING = new SeasonEnum("春天");
SUMMER = new SeasonEnum("夏天");
AUTUMN = new SeasonEnum("秋天");
WINTER = new SeasonEnum("冬天");
$VALUES = (new Day[] {SPRING , SUMMER , AUTUMN , WINTER});
}
}
通过反编译它继承自java.lang.Enum,Enum抽象类中具体方法,除了toString(),其它方法都被final修饰,子类不可以被重写,所以只能调用自己父类中的了:
Enum方法 | 说明 |
---|---|
int compareTo(E o) | 该方法用于与指定枚举进行大小比较,是通过ordinal()索引值进行比较 |
Class getDeclaringClass() | 获取指定枚举的Class对象 |
String name() | 返回此枚举的名称 |
int ordinal() | 返回次枚举在枚举值中的索引值,默认从0开始 |
String toString() | 返回枚举常量的名称 |
static <T extends Enum> T valueOf(Class enumType, String name) | 根据枚举类类型和指定枚举名称获取枚举实例 |
//调用编译器生成的方法
SeasonEnum[] seasonEnum = SeasonEnum.values();
System.out.println(Arrays.toString(seasonEnum)); //[SPRING, SUMMER, AUTUMN, WINTER]
System.out.println("valueof():"+SeasonEnum.valueOf(seasonEnum[0].name())); //valueof():SPRING
SeasonEnum spring = SeasonEnum.SPRING;
System.out.println("ordinal():"+spring.ordinal()); // ordinal():0
System.out.println("compareTo():"+spring.compareTo(SeasonEnum.WINTER)); //compareTo():-3
System.out.println("getDeclaringClass():"+spring.getDeclaringClass()); //getDeclaringClass():class cn.boshao.test.SeasonEnum
System.out.println("name():"+spring.name()); //name():SPRING
System.out.println("toString():"+spring.toString()); //toString():SPRING
System.out.println("valueOf():"+SeasonEnum.valueOf(SeasonEnum.class,"SUMMER")); //valueOf():SUMMER
包含抽象方法的枚举类:
/**
*
*@author 高波
*/
enum SeasonEnum{
SPRING("春天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
},SUMMER("夏天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
},AUTUMN("秋天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
},WINTER("冬天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
};
/**
* 假设设定年平均气温15摄氏度
*
*
*/
private static final Integer avgTemperature = 15;
private String seasonName;
private SeasonEnum(String seasonName){
this.seasonName = seasonName;
}
/**
* 计算传入当前温度和年平均气温温差
*
*/
public abstract Integer calculateTemperature(Integer temperature);
public String getSeasonName() {
return this.seasonName;
}
}
在枚举类中定义抽象方法时不能把枚举类也定义为抽象类,这一过程系统会自己处理,我们尽管使用。
实现接口的枚举类
/**
* 定义一个接口,供枚举实现
*
* @author 高波
*
*/
interface SeasonStatus{
void say();
void raalSay();
}
/**
* @author 高波
*
*/
enum SeasonEnum implements SeasonStatus{
SPRING("春天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
@Override
public void say() {
System.out.println("春回大地");
}
},SUMMER("夏天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
@Override
public void say() {
System.out.println("烈日炎炎");
}
},AUTUMN("秋天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
@Override
public void say() {
System.out.println("秋天气爽");
}
},WINTER("冬天"){
@Override
public Integer calculateTemperature(Integer temperature) {
return avgTemperature - temperature;
}
@Override
public void say() {
System.out.println("冻的打滚");
}
};
/**
* 假设设定年平均气温15摄氏度
*
*
*/
private static final Integer avgTemperature = 15;
private String seasonName;
private SeasonEnum(String seasonName){
this.seasonName = seasonName;
}
@Override
public void raalSay() {
System.out.println("我爱四季");
}
/**
* 计算传入当前温度和年平均气温温差
*
*/
public abstract Integer calculateTemperature(Integer temperature);
public String getSeasonName() {
return this.seasonName;
}
}
枚举虽然不能继承,但是可以实现一个或多个接口,与普通类实现接口是一摸一样。