Java基础系列-Enum深入解析

作者简介:大家好,我是码炫码哥,前中兴通讯、美团架构师,现任某互联网公司CTO,兼职码炫课堂主讲源码系列专题


代表作:《jdk源码&多线程&高并发》,《深入tomcat源码解析》,《深入netty源码解析》,《深入dubbo源码解析》,《深入springboot源码解析》,《深入spring源码解析》,《深入redis源码解析》等


联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

一、概述

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

定义一个枚举,其实就是定义一个继承抽象类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. 添加静态块为这些静态枚举常量赋值

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值