Java Enum类语法和用法解析
一.语法
1. Enum的全称为enumeration,中文俗称枚举类,学过C/C++等语言的人,应该都对它略知一二.
但在Java语言规范中,是在JDK 5版本中才引入的,存放在 java.lang 包中。在Java版的Enum实质是语法糖,其声明方式如下:
package felix.fu
public enum Color{
RED,
BLUE,
BLACK,
YELLOW,
GREEN
}
enum是用来声明枚举的关键字,声明定义的类都隐含继承了一个父类(java.lang.Enum<E>),因此枚举不能再继承,但仍可实现接口。
该父类有两个私有属性name(枚举类型的名称)和ordinal(枚举实例被创建的序数),分别通过name()和ordinal()暴露出来了.
定义在枚举类型里的每一个枚举实例都将映射到Enum的子类中,其实例的名称和在枚举类型里定义的顺序都会传入到这个构造函数里
protected Enum(String name, int ordinal)。
2. 如果想更清楚了解一下Enum,可以用反编译工具把自己定义的枚举反编译一下就一目了然了,它就是一个普通的类,
只是Java语言规范从Code角度进行了限制,执行javap felix.fu.Color命令如下:
public final class Color extends java.lang.Enum{
public static final Color RED;
public static final Color BLUE;
public static final Color BLACK;
public static final Color YELLOW;
public static final Color GREEN;
static {};
public static Color[] values();
public static Color valueOf(java.lang.String);
}
3. 如果定义的枚举有自己的构造函数必须声明私有的
二.用法
1.使用场景
(1) 常用于对同一类常量进行分类
(2) 声明接口方法时,输入参数类型采用枚举比用原始类型值常量更严谨.
(3) 常量有时往往不仅仅只是一个值,有可能会包含多个属性,此时很适合用枚举
(4) 有时常量对象需要从配置文件中读取其描述信息或者UI显示信息,此时也适合用枚举
(5) 从Java语法层面来说,枚举可以在switch使用,在if中可直接进行比较
(6) 声明枚举属性时最好用public final修饰,使用起来会非常方便
(7) 自定义枚举时,建议不要使用自带的name()和ordinal()方法返回值来与原始值类型转换,这样业务不依赖其枚举的名字和顺序,如下:
public enum Color {
RED(0), BLUE(1), BLACK(2), YELLOW(3), GREEN(4);
public final int value;
/**
* @param value
*/
private Color(int value) {
this.value = value;
}
public static Color getInstance(int value) {
for (Color code : values()) {
if (code.value == value)
return code;
}
return null;
}
}
2.实例:声明了一个基于枚举的简单异常框架,采用枚举来实现
public interface ExceptionCode {
/**
* 返回异常码
*/
String getErrorCode();
/**
* 返回异常描述
* @param args 异常描述所用到的占位符值数组
*/
String getErrorCause(Object... args);
}
public enum DbExceptionCode implements ExceptionCode {
UNIQUE_KEY("10001", "主键约束错误"),
FOREIGN_KEY("10002", "外键约束错误");
public final String errorCode;
public final String errorName;
private DbExceptionCode(String errorCode, String errorName) {
this.errorCode = errorCode;
this.errorName = errorName;
}
@Override
public String getErrorCode() {
return errorCode;
}
@Override
public String getErrorCause(Object... args) {
// TODO need to read from configuration by errorCode
String errorCause = "";
return MessageFormat.format(errorCause, args);
}
}
public class DbException extends RuntimeException {
protected String errorCode;
protected String errorCause;
/**
* message format:BussinessErrorCode:BussinessErrorCause eg: 10010:无效Barcode[1000052]
*
* @param errorCode
* error code of bussiness
* @param errorCause
* error cause of bussiness
* @param cause
*/
protected DbException(String errorCode, String errorCause, Throwable cause) {
super(errorCode + ":" + errorCause, cause);
this.errorCode = errorCode;
this.errorCause = errorCause;
}
public DbException(ExceptionCode exceptionCode, Object... args) {
this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(args));
}
public DbException(Throwable cause, ExceptionCode exceptionCode, Object... args) {
this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(args), cause);
}
public DbException(ExceptionCode exceptionCode, Throwable cause) {
this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(), cause);
}
protected DbException(String errorCode, String errorCause) {
this(errorCode, errorCause, null);
}
/**
* @return the errorCode
*/
public String getErrorCode() {
return errorCode;
}
/**
* @return the errorCause
*/
public String getErrorCause() {
return errorCause;
}
}
三. 弊端: 就是与原始值类似转换起来有点麻烦