基本概念
Java中的Enum是一种包含一组固定常量的数据类型
可以将Java枚举看作具有一组固定常量(不变的变量)的类。Java enum常量是静态的,并且是隐式的final。它从JDK 1.5开始被使用
Java Enum在内部继承了Enum类,因此它不能继承任何其他类,但是可以实现许多接口。 我们可以在Java枚举中包含字段,构造函数,方法和main方法
tips:
枚举可提高类型安全性
枚举可轻松用于切换
可以遍历枚举
枚举可以具有字段,构造函数和方法
Enum可以实现许多接口,但是不能扩展任何类,因为它在内部扩展了Enum类
示例:
public class EnumTest {
//在类内部定义一个枚举类型
enum SeasonEnum {
SPRING,
SUMMER,
FALL,
WINTER;
}
public static void main(String[] args) {
SeasonEnum season = SeasonEnum.SPRING;
}
}
自定义属性和普通方法
Java枚举中允许定义属性和方法,但必须在枚举实例序列的最后一个分号后再添加。Java 要求必须先定义枚举实例在前面
public class EnumTest2 {
enum SeasonEnum {
SPRING(0,"the first season"),
SUMMER(1,"the second season"),
FALL(2,"the third season"),
WINTER(3,"the fourth season");
private int code;
private String desc;
//枚举的构造方法默认且只能是private的。
SeasonEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 根据季节的code值获取对应的季节的描述
* @param code 季节code
* @return 季节描述
*/
public static String getDescByCode(int code) {
for (SeasonEnum s : SeasonEnum.values()
) {
if (s.code == code) {
return s.desc;
}
}
return null;
}
@Override
public String toString() {
return "SeasonEnum{" +
"code=" + code +
", desc='" + desc + '\'' +
'}';
}
}
public static void main(String[] args) {
for (SeasonEnum s : SeasonEnum.values()
) {
System.out.println(s);
}
System.out.println(SeasonEnum.getDescByCode(1));
}
}
自定义抽象方法
与常规抽象类一样,enum类允许我们为其定义抽象方法,然后使每个枚举实例都实现该方法,以便产生不同的行为方式,注意abstract关键字对于枚举类来说并不是必须的如下
public class EnumTest3 {
enum WeekEnum {
MONDAY("星期一") {
@Override
public String getInfo() {
return "the first day of week";
}
},
TUESDAY("星期二") {
@Override
public String getInfo() {
return "the second day of week";
}
};//记住要用分号结束
private String desc;//描述
private WeekEnum(String desc){
this.desc=desc;
}
public abstract String getInfo(); //抽象方法
}
public static void main(String[] args) {
WeekEnum a = WeekEnum.MONDAY;
System.out.println(a.getInfo());
}
}
output:
the first day of week
枚举(Enum)的常用方法
方法 | 描述 |
---|---|
public final int ordinal() | 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零) |
public final String name() | 返回此枚举常量的名称 |
public String toString() | 返回声明中包含的此枚举常量的名称,一般会被重写 |
public final int compareTo(E o) | 比较此枚举与指定对象的顺序 |
public final Class getDeclaringClass() | 返回与此枚举常量的枚举类型相对应的 Class 对象 |
public static <T extends Enum> T valueOf(Class enumType, String name) | 返回具有指定名称指定枚举类型的枚举常量,如: WeekEnum MONDAY = Enum.valueOf(WeekEnum.class, “MONDAY”); |
应用
switch
JDK7以后,switch已经支持
int
、char
、String
、enum
类型的参数。
public static void main(String[] args) {
SeasonEnum season = SeasonEnum.SPRING;
switch (season) {
case SPRING:
System.out.println("It's spring");
break;
case SUMMER:
System.out.println("It's summer");
break;
default:
System.out.println("It's fall or winter");
}
}
单例模式
Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次,因此枚举对象具有唯一性,
public enum EnumSingleton {
INSTANCE;
}
class Test {
public static void main(String[] args) {
EnumSingleton a = EnumSingleton.INSTANCE;
EnumSingleton b = EnumSingleton.INSTANCE;
System.out.println(a == b);
}
}
output:
true
实用场景
如果需要将一个已有的类改造为单例类,也可以使用枚举的方式来实现。
public class Singleton {
private Singleton(){} //0. 首先将Singleton类的构造函数设置为private私有的
public static enum SingletonEnum { //1. 在已有的类(Singleton)中定义一个静态的枚举类型
SINGLETON; //2. 定义枚举类型实例对象
private Singleton instance; //3. 定义一个Singleton类型的对象instance
private SingletonEnum(){
instance = new Singleton(); //4. 在SingletonEnum的私有构造函数中创建一个Singleton的实例对象
}
public Singleton getInstance() {
return instance; //5. 在getInstance()方法中返回该对象
}
}
}
class Test2 {
public static void main(String[] args) {
Singleton singleton = Singleton.SingletonEnum.SINGLETON.getInstance();
Singleton singleton1 = Singleton.SingletonEnum.SINGLETON.getInstance();
System.out.println(singleton == singleton1);
}
}