最近Github上项目中看到了用枚举来列举错误码,听就是听过枚举,但没实际用过,所以来学习下
1. Enum
Enum是一种受限制的类,编译时IDE会为enum生成一个相关的类,这个类继承自 java.lang.Enum,且具有自己的方法
1.1 先来看看Enum类源码
public abstract class Enum< E extends Enum > implements Comparable, Serializable {
// 枚举实例的名字
private final String name;
public final String name() {
return name;
}
// 枚举声明的次序
private final int ordinal;
public final int ordinal() {
return ordinal;
}
// 构造方法,只能编译器调用,说明枚举有名字和次序
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
// 应该调用这个来获取名字
public String toString() {
return name;
}
// 因为JVM会确保只有一个实例,所以可用==来比较
public final boolean equals(Object other) {
return this == other;
}
// 重写:比较的是声明次序
public final int compareTo(E o) {
Enum> other = (Enum>)o;
Enum self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
// 返回枚举实例的数组
public static > T valueOf(Class enumType, String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}
1.2 简单实例
public enum Animal {
DOG, CAT, BIRD, LION, ELEPHANT;
}
1.3 简单实例的反编译源码
// 声明为final类
final class Animal extends Enum{
// 编译器生成的两个方法:values、valueOf
public static Animal[] values(){
return (Animal[])$VALUES.clone(); // 克隆一个
}
public static Animal valueOf(String s){
return (Animal)Enum.valueOf(com/howl/enumn/Animal, s);
}
// 私有构造方法
private Animal(String s, int i){
super(s, i);
}
// 我们写的变量,本质为实例变量
public static final Animal DOG;
public static final Animal CAT;
public static final Animal BIRD;
public static final Animal LION;
public static final Animal ELEPHANT;
private static final Animal $VALUES[];
// 实例化
static {
DOG = new Animal("DOG", 0);
CAT = new Animal("CAT", 1);
BIRD = new Animal("BIRD", 2);
LION = new Animal("LION", 3);
ELEPHANT = new Animal("ELEPHANT", 4);
$VALUES = (new Animal[] {
DOG, CAT, BIRD, LION, ELEPHANT
});
}
}
各实例会在静态代码块被赋值,根据JVM的加载过程,我们知道Enum的创建过程是线程安全的
至此大家应该对Enum有稍微的了解,那么再来看看枚举的常用方法
1.4 常用方法
返回值 | 方法名 | 解释 |
---|---|---|
Enum[] | values() | 返回enum实例数组 |
Enum | valueOf() | 返回指定名字的enum实例 |
int | compareTo() | 实现了该接口,可比较 |
int | ordinal() | 返回声明次序 |
String | name() | 返回实例名 |
Enum | getDeclaringClass() | 返回enum类型 |
boolean | equals() | 比较是否同一对象 |
- JVM保证枚举类型仅一个常量实例,所以也可用 == 来比较enum实例
1.5 简单使用
如果枚举不添加任何方法,枚举值默认为从0开始的有序数值
public class EnumDemo {
// 约定值大写,序号默认从0开始
enum Animal {
DOG, CAT, BIRD, LION, ELEPHANT;
}
public static void main(String[] args) {
// 遍历枚举值
for (Animal value : Animal.values()) {
System.out.println(value.ordinal() + ":" + value);
}
// 其方法
Animal dog = Animal.DOG;
System.out.println(dog.name());
System.out.println(dog.getDeclaringClass());
System.out.println(Animal.valueOf("DOG") == dog);
}
}
0:DOG
1:CAT
2:BIRD
3:LION
4:ELEPHANT
DOG
class enumm.EnumDemo$Animal
true
2. 自定义方法、变量
编译器会为枚举类自动继承Enum,所以无法再使用继承了,其余方面和普通类没什么区别
注意:
- 若为枚举定义方法,那么必须先声明实例,且在最后一个实例后加分号
- Java中不允许使用赋值符号 = 为枚举常量赋值,但可自定义方法来赋值
- 父类方法只有toString没有被声明为final,那么只有toString才能被重写
public enum Animal {
// 声明实例
DOG(1,"狗"),
CAT(2,"猫"),
BIRD(4,"鸟"),
LION(8,"狮子"),
ELEPHANT(16,"大象");
// 私有属性
private int num;
private String name;
// 获取内部私有属性的接口
public int getNum() {
return num;
}
public String getName() {
return name;
}
// 构造方法只能声明为private,或者不声明
private Animal(int num,String name){
this.num = num;
this.name = name;
}
// 可以重写toString来代替get属性的方法
@Override
public String toString() {
return "Animal{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
// 静态方法
public static void main(String[] args) {
for (Animal value : Animal.values()){
System.out.println(value.toString());
}
}
}
Animal{num=1, name='狗'}
Animal{num=2, name='猫'}
Animal{num=4, name='鸟'}
Animal{num=8, name='狮子'}
Animal{num=16, name='大象'}
3. 应用
枚举可以将常量组织起来,统一进行管理,而且安全性有保证,那么其常见于错误码的同一管理
public enum ErrorCodeEnum {
SUCCESS(0000,"成功"),
PARAM_TYPE_ERROR(1000,"参数类型错误"),
USER_NOT_LOGIN(2000,"用户未登录"),
SERVER_ERROR(3000,"服务端错误");
private Integer code;
private String msg;
public Integer getCode(){
return code;
}
public String getMsg(){
return msg;
}
private ErrorCodeEnum(Integer code, String msg){
this.code = code;
this.msg = msg;
}
}
参考
https://www.cnblogs.com/jingmoxukong/p/6098351.html