浅学JAVA枚举二:为什么要使用枚举?

115 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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("无");
    }

}

三丶枚举是单例的

我们知道单例模式天然就是线程安全的,而且效率较高,而我们的枚举就是一个完美的单例对象

  1. 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类型就会抛出异常

  1. Enum无法克隆,调用Clone()方法会抛出异常
protected final Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}
  1. 采用实现java.io.Serializable接口,反序列化方式不会创建对象

在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象,不存在创建对象的可能。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,所以此方式也行不通。

总结

为什么要使用枚举? 1.枚举提供更简单的写法 2.枚举可以更好的支持switch 语句 3.枚举是单例的

摘要:blog.csdn.net/CS5686/arti…