关于java:Enum深入解析

9次阅读

共计 3048 个字符,预计需要花费 8 分钟才能阅读完成。

人生有涯,学海无涯

一、概述

枚举就是一个语法糖成果。

定义一个枚举,其实就是定义一个继承抽象类 Enum 的类。

理解了 Enum,就能理解枚举。

二、Enum 解析

2.1 接口

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {}

枚举类实现了 Comparable 和 Serializable 接口,那么也就意味着,每个枚举类都领有比拟(有序)和序列化性能。

2.2 属性

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {
    private final String name;
    private final int ordinal;
    public final String name() {return name;}
    public final int ordinal() {return ordinal;}    
}

这两个属性是枚举的内置属性,name 示意的是枚举值的名称,ordinal 示意的是枚举值的序号。

其作用前面再说

2.3 结构器

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
}

Enum 中只有这一个结构器,其申明为 protected 就是为了继承它的子类(咱们定义的各种枚举)来调用的。

2.4 equals 办法

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {public final boolean equals(Object other) {return this==other;}
}

默认的 equals 办法底层就是应用 == 实现的,所以在枚举的比拟应用 equals 和 == 都是能够的。前提是没有在枚举类中重写 equals 办法。

咱们能够在自定义的枚举类中重写该办法,来实现咱们本人的比拟形式。

2.5 禁用的性能

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {protected final Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException();
    }
    protected final void finalize() {}
    private void readObject(ObjectInputStream in) throws IOException,
    ClassNotFoundException {throw new InvalidObjectException("can't deserialize enum");
    }
    private void readObjectNoData() throws ObjectStreamException {throw new InvalidObjectException("can't deserialize enum");
    }   
}

这四个办法均是被禁用的办法:

  • 克隆:目标为了保障单例惟一
  • finalize:禁用终援用
  • 序列化中禁用 readObject 和 readObjectNoData 办法:目标为了保障单例惟一

2.6 compareTo 办法

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {public final int compareTo(E o) {Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }
}

这是实现了接口 Comparable 中的办法。用于定义比拟的形式,能够看出这里是应用枚举值的序号作为比拟条件的。

2.7 办法

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {
    public static <T extends Enum<T>> T valueOf(Class<T> 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);
    }
}

该办法的作用是获取到指定枚举类型中指定枚举名称的枚举值。

三、枚举的实现

枚举是一种编译器语法糖。

咱们应用 enum 关键字定义一个枚举,编译之后,编译器会对其进行加工,具体如下:

  1. 编译成为 class 类型,并继承自 Enum
  2. 增加动态的 values 办法,用于获取所有枚举值的数组
  3. 增加 valueOf 办法,实现 Enum 中的 valueOf 办法,能够依据具体的枚举值名称字符串获取对应的枚举值
  4. 增加公有结构器,其中调用 Enum 中定义的惟一的结构器
  5. 定义动态常量枚举值
  6. 增加动态块为这些动态枚举常量赋值

通过下面一些列加工之后,枚举类被解析为一个一般的类,类名不变。

四、Demo

public enum RedActiveStatusEnum {NO_START("未开始", 1),
    READY("筹备中", 2),
    PROCESSING("进行中", 3),
    END_NO_FINISH("已完结支付未实现", 4),
    END_YES_FINISH("已完结支付实现", 5),
    END_FORCE("强制完结", 6);

    private String name;
    private Integer value;

    private RedActiveStatusEnum(String name, Integer value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Integer getValue() {return value;}

    public void setValue(Integer value) {this.value = value;}


    public static void main(String[] args) {RedActiveStatusEnum.END_FORCE.getValue();
    }
}
正文完
 0