深入掌握Java中的enum

Posted fina1ly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入掌握Java中的enum相关的知识,希望对你有一定的参考价值。

对于要在程序中要表示有限种类的某事物,一般我们可以采用两种方式,一是使用:public static final String 常量;二是使用enum来表示。一般而言前者简单,但是不能够很好的提供更多的信息,而Java中的enum相比而言,却十分的强大,而且更加的专业。

1. 最间C风格的enum:

/**
 * 数据源的类别:master/slave
 */
public enum DataSources {
    MASTER0, MASTER1, SLAVE0, SLAVE1, SLAVE2,  SLAVE2
}

这是最简单的enum, 和C语言中的几乎一样。简单简洁但是功能也很弱。

2. enum 的本质

Java中的enum的本质是一个继承java.lang.Enum的类。所以他就比C风格的enum更加的强大。它可以有属性,方法,构造函数等等,下面看一个例子:

import org.apache.commons.lang.StringUtils;
/**
 * 错误码枚举*/
public enum ErrorCodeEnum {
    /** 系统异常 */
    SYSTEM_ERROR("system_error", "系统异常"),
    /** 参数非法 */
    ILLEGAL_ARGUMENT("illegal_argument", "参数非法"),
    /** 签名非法 */
    ILLEGAL_SIGN("illegal_sign", "签名非法"),

    // ... ...

    /** 注册码非法 */
    ILLEGAL_REG_CODE("illegal_reg_code", "注册码非法");

    /** 枚举码 */
    private String code;
    /** 枚举描述 */
    private String desc;

    private ErrorCodeEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    public String getCode() {
        return code;
    }
    public String getDesc() {
        return desc;
    }
    
    /**
     * 根据枚举码获取枚举
     * @param code 枚举码
     * @return 枚举
     */
    public static final ErrorCodeEnum getByCode(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        for (ErrorCodeEnum item : ErrorCodeEnum.values()) {
            if (StringUtils.equals(item.getCode(), code)) {
                return item;
            }
        }
        return null;
    }
}

我们看到 ErrorCodeEnum  具有属性 String code 和 String desc,并且具有一个私有的构造函数。原因是我们的枚举常量需要使用这个私有的构造函数的定义:SYSTEM_ERROR("system_error", "系统异常") 就是调用的枚举的私有构造函数:private ErrorCodeEnum(String code, String desc);所以其实ErrorCodeEnum 中定义的枚举常量 SYSTEM_ERROR, ILLEGAL_ARGUMENT 等其实就相当于 ErrorCodeEnum 的一个实例而已,因为它们是调用ErrorCodeEnum 的私有构造函数生成的。而 ErrorCodeEnum 的属性 String code 和 String desc,是为了更好的提供更加详细的错误信息而定义的。而且在枚举ErrorCodeEnum中还可以定义其它的各种辅助方法。

所以枚举的本质是一个继承与java.lang.Enum的类,枚举常量就是枚举的一个个的实例。枚举可以有属性和方法,来强化枚举的功能。枚举一般而言在Java中不是很好理解,一般掌握了枚举背后的本质,那么理解起来就毫无难度了。

3. 枚举的常用方法

public static void main(String[] args){
        System.out.println(SYSTEM_ERROR.name());
        System.out.println(SYSTEM_ERROR.ordinal());
        System.out.println(SYSTEM_ERROR.toString());
        for(ErrorCodeEnum e : ErrorCodeEnum.values()){
            System.out.println(e.name());
            System.out.println(e.getDesc());
        }
        
        System.out.println(ErrorCodeEnum.SYSTEM_ERROR.name());
        System.out.println(ErrorCodeEnum.valueOf(ErrorCodeEnum.class, "ILLEGAL_ARGUMENT"));
    }

String name() : Returns the name of this enum constant, exactly as declared in its enum declaration. 返回枚举常量声明时的字符串。

int    ordinal() : 返回枚举常量的声明时的顺序位置,像数组的索引一样,从0开始。

valueOf(Class<T> enumType, String name) : 其实是从 枚举常量的字符串到 枚举常量的转换,相当于一个工厂方法。

name() 方法是从 枚举常量 到 字符串的转换,而 valueOf 是字符串到 枚举常量的转换。

values() : 该方法是一个隐式的方法,All the constants of an enum type can be obtained by calling the implicit public static T[] values() method of that type. 用于遍历枚举中的所有的枚举常量。

 

4、枚举的线程安全单例模式

enum SingletonDemo{
    INSTANCE;
    public void otherMethods(){
        System.out.println("Something");
    }
}

简简单单的一点代码就实现了一个线程安全的单例,与其说是写法鬼斧神工,不如说是恰如其分地应用了enum的性质。

 

以上是关于深入掌握Java中的enum的主要内容,如果未能解决你的问题,请参考以下文章

深入理解 Java 枚举

java中的enum

Thinking in java Chapter19 枚举类型

48个值得掌握的JavaScript代码片段(上)

C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法

java中enum的values()方法定义在哪里呢?