枚举——enum

一、什么是枚举
枚举是我们自己定义的一个集合,当我们要使用这个集合的时候,只能使用集合里的元素,不是这个集合里的元素我们就不可以使用。
二、枚举可以干什么
枚举的出现主要是为了代替静态常量,
常量有什么弊端
1.常量必须定义类型,但是如果定义了类型就不明确它定义的意义。
2.命名局限性,有时候我们会忘记自己定义的变量是干什么,例如:

 private static final int MEN=0;
 private static final int WOMEN=1;

这些变量完全可以做加减运算,但是这可能不是我们的本意,我们就仅仅想让他们表示性别,字面上的意思。当我们输出的时候,我们想让他输出的是MEN,但是用静态变量只能输出0.如果忘记了0所代表的含义,有时候不得不翻翻0所代表的含义。这样是没有可读性的

枚举的应用场景
1.作为普通的常量使用,如四季,星期,颜色
2.对于有穷个对象集合,可以配合switch使用
3.当我们可能会用到很多的静态常量的时候,如果全写在一个文件里,容易造成命名混淆,用枚举就可以就解决这个问题。
4.枚举不仅仅能代表常量使用,还可以添加自己的方法。
三,枚举的底层原理
所有的enum默认继承自Enum,看一下Enum源码

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, 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;
    }
    public final boolean equals(Object other) {
        return this==other;
    }
    public final int hashCode() {
        return super.hashCode();
    }
	
	protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
    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;
    }
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }
    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);
    }
    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");
    }
     protected final void finalize() { }
}

在源代码中,可以得出以下几个信息
1.Enum有两个成员变量:name和ordinal。其中,name用于记录枚举常量的名字,ordinal用于记录枚举常量在声明时的顺序,从0开始计数。
2.Enum类有一个构造器,分别为name和ordinal赋值
3.Enum重写了toString方法,返回枚举常量的name
4.Enum有equals方法,直接用==比较
5.Enum实现了Comparable接口,直接比较枚举常量ordinal的值。
6.Enum有一个valueOf方法,根据枚举类型以及name返回一个枚举常量。
7.Enum不允许克隆,直接抛出异常
8.Enum不允许反序列化,用于保证枚举永远是单例的。

自己定义一个枚举类

public enum Week {
    MONDAY(0),TUESDAY(1),WEDNESDAY(2),
    THURSDAY(3),FRIDAY(4),SATURDAY(5),SUNDAY(6);
    int num;
    Week(int num){
        this.num=num;
    }
}

我们自己定义的枚举类实际上在底层是这样的结构:

public final class Week extends Enum{
    private static final Week MONDAY;
    private static final Week TUESDAY;
    private static final Week WEDNESDAY;
    private static final Week THURSDAY;
    private static final Week FRIDAY;
    private static final Week SATURDAY;
    private static final Week SUNDAY;
    int num;
    private static final Week $VALUES[];
    static {
        MONDAY=new Week("MONDAY",0,1);
        TUESDAY=new Week("TUESDAY",1,2);
        WEDNESDAY=new Week("WEDNESDAY",2,3);
        THURSDAY=new Week("THURSDAY",3,4);
        FRIDAY=new Week("FRIDAY",4,5);
        SATURDAY=new Week("SATURDAY",5,6);
        SUNDAY=new Week("  SUNDAY",6,7);
        $VALUES=(new Week[]{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY});
    }
    private Week(String s,int i,int j){
        super(s,i);
        num=j;
    }
    public static Week[] values(){
        return (Week[])$VALUES.clone();
    }
    public static Week valueOf(String s){
        return (Week) Enum.valueOf(Week,s);
    }
}

四,使用枚举需要注意的点。
1.枚举不允许继承类,JVM在生成枚举时已经继承了Enum类,由于java是单继承语言,所以不允许在继承额外的类。
2.枚举允许实现接口,因为枚举本身就是一个类,类可以实现多个接口
3.枚举可以用==比较,JVM会为每一个枚举实例生成一个类对象,这个类对象是用public static final修饰的,在static代码块中初始化,是一个单例。
4.不可以继承枚举,因为所有枚举默认是final的。
5.枚举本身就是一种对单例模式友好的,它是实现单例模式的一种很好方法。
6.枚举的compareTo()方法比较的是ordinal的值
7.枚举的equals()比较的是枚举对象的内存地址,作用与==等价

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值