携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
前言:
在项目中我们可能会经常使用枚举,但是我们可能不清楚为什么要使用枚举,不是接口常量也可以替代枚举的一些操作吗? 如果你也有这样的疑惑,相信我阅读这篇文章可以解决你的疑惑。
一丶枚举提供更简单的写法
我们先看两个例子,一个不使用枚举,但是类似枚举的例子,还有一个使用枚举的例子
- 不使用枚举实现枚举的效果
public class Color {
private Color() {} // Prevents objects from being created externally
public static final Color RED = new Color();
public static final Color AMBER = new Color();
public static final Color GREEN = new Color();
}
我们使用的时候可以这样写
Color trafficLightColor = Color.RED;
- 使用枚举类型的效果
public enum Color { RED, AMBER, GREEN };
上面两种情况都可以提供来自编译器相同级别的检查,但是第一次情况会要使用更多的代码实现功能,而第二种情况代码量就可以大大减少
二丶枚举可以更好的支持switch 语句
switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开 始,switch 支持String 类型了,同时 case 标签必须为字符串常量或字面量。如果我们需要对一个存放了几个属性的对象使用switch语句,我们就使用不了,而这里使用枚举就可以实现这种效果
public static void main(String[] args) {
FB_TYPE wrinkled = FB_TYPE.WRINKLED;
switch (wrinkled){
case SWEET:
System.out.println("SWEET");
break;
case GREEN:
System.out.println("GREEN");
break;
case WRINKLED:
System.out.println("WRINKLED");
break;
default:
System.out.println("无");
}
}
三丶枚举是单例的
我们知道单例模式天然就是线程安全的,而且效率较高,而我们的枚举就是一个完美的单例对象
- enum类无法使用反射方式来创建,使用反射方式来创建会抛出异常
@CallerSensitive
@ForceInline // to ensure Reflection.getCallerClass optimization
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, clazz, modifiers);
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
因为我们反射的newInstance方法判断如果是Enum类型就会抛出异常
- Enum无法克隆,调用Clone()方法会抛出异常
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
- 采用实现java.io.Serializable接口,反序列化方式不会创建对象
在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象,不存在创建对象的可能。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,所以此方式也行不通。
总结
为什么要使用枚举? 1.枚举提供更简单的写法 2.枚举可以更好的支持switch 语句 3.枚举是单例的