当前位置:首页 » JAVA技术教程

Java必知必会之----Enum枚举类揭秘

2018-08-09 08:02 本站整理 浏览(2)

【原理】

写一个枚举,相信大家都会,如:

1public enum City {Guangzhou, Shenzhen, Dongguan}

这是个城市的枚举类,包含广州、深圳、东莞三个城市枚举值,但是它怎么用呢?它的背后的真面目是怎样的呢?

下面我们来反编译一下这个枚举,结果得出:

 1public final class City  extends Enum<City>  {
2    public static final City[] values() {
3        return (City[]) $VALUES.clone();
4    }
5    public static City valueOf(String name) {
6        return (City) Enum.valueOf(City, name);
7    }
8    // 构造函数
9    private City(String s, int i) {
10        super();
11    }
12    public static final City Guangzhou;
13    public static final City Shenzhen;
14    public static final City Dongguan;
15
16    private static final City $VALUES[];
17    // 实例化枚举
18    static {
19        Guangzhou = new City("Guangzhou", 0);
20        Shenzhen = new City("Shenzhen", 1);
21        Dongguan = new City("Dongguan", 2);
22        $VALUES = (new City[] { Guangzhou, Shenzhen, Dongguan });
23    }
24}

从这个类中我们可以看出几点:

1)是个类 并且是final类,继承与java.lang.Enum类 不可继承。

2)用static块初始化。

3)定义了几个final类型的City对象,并且在static块中初始化。

由此可以知道,enum本质是一个final类,而JavaAPI的设计出的这个Enum,是一个被封装之后的类,旨在提供一种代码简洁而高效的类型管理组件,简化开发者编码。这当然是废话啦,各位看看,同样是功能的两种写法哪一种更简洁?哪一种更值得用?

我们再来看看enum接口类的源码:

1public abstract class Enum<E extends Enum<E>>
2        implements Comparable<E>, Serializable {
3    //枚举常量名称
4    private final String name;
5  //返回枚举常量名称
6    public final String name() {
7        return name;
8    }
9    //枚举常量的序数 初始值为0 根据位置而得出
10    private final int ordinal;
11//    返回枚举常量的序数
12    public final int ordinal() {
13        return ordinal;
14    }
15    //私有构造函数,程序无法直接调用改函数进行初始化
16    //它用于由响应枚举类型声明的编译器发出的代码
17    //@param name:枚举常量的名称
18    //@param ordinal: 枚举常量的序数
19    protected Enum(String name, int ordinal) {
20        this.name = name;
21        this.ordinal = ordinal;
22    }
23    //和name()是一个意思
24    public String toString() {
25        return name;
26    }
27    //判断是否相同对象的函数
28    public final boolean equals(Object other) {
29        return this==other;
30    }
31    //为枚举返回一个hashCode
32    public final int hashCode() {
33        return super.hashCode();
34    }
35    //克隆函数
36    protected final Object clone() throws CloneNotSupportedException {
37        throw new CloneNotSupportedException();
38    }
39    //比较此枚举与指定对象的顺序(编号)。
40    //在该对象小于、等于或大于指定对象时,分别返回负整数、零或正整数。
41    //枚举常量只能与相同枚举类型的其他枚举常量进行比较。
42    //该方法实现的自然顺序就是声明常量的顺序。 
43    public final int compareTo(E o) {
44        Enum<?> other = (Enum<?>)o;
45        Enum<E> self = this;
46        if (self.getClass() != other.getClass() && // optimization
47            self.getDeclaringClass() != other.getDeclaringClass())
48            throw new ClassCastException();
49        return self.ordinal - other.ordinal;
50    }
51// 以下方法略过....
52}

有了这个抽象类Enum的源码,我们基本上知道枚举是怎么使用的了,下面是一些常用的方法:

方法名

返回值

说明

name()

String

返回枚举的名称

ordinal()

int

返回枚举常量的序数

compareTo(E o)

int

比较此枚举与指定对象的顺序(编号)。

在该对象小于、等于或大于指定对象时,分别返回负整数、零或正整数。

枚举常量只能与相同枚举类型的其他枚举常量进行比较。

该方法实现的自然顺序就是声明常量的顺序

     


【使用方式】

Enum类实现三种枚举:

1)最常用:

1public enum Num {
2    ONE,TWO,THREE;
3}

 

2)定义带参构造函数:


1public enum EnumTest{
2    ONE("1","YI");
3    private String name;
4    private String  value;
5    //一个参
6    private EnumTest(String name){
7        this.name=name;
8    }
9    //两个参数
10    private EnumTest(String name,String value){
11        this.name=name;
12        this.value=value;
13    }
14    //...多个参数
15    public static void main(String[] args) {
16        System.out.println(EnumTest.ONE.name);
17        System.out.println(EnumTest.ONE.value);
18    }
19}

 

3)抽象方法实现:

 

 1public enum EnumTest{
2    ONE("1") {
3        @Override
4        public void handle() {
5            // TODO Auto-generated method stub
6        }
7    };
8    private String name;
9    private EnumTest(String name){
10        this.name=name;
11    }
12    //定义抽象方法
13    public abstract void handle();
14    public static void main(String[] args) {
15        //调用
16        EnumTest.ONE.handle();
17    }
18}

 

【注意事项】

1)不能继承,因为枚举类本身已经继承了Enum抽象类,而Java是单继承 

2)枚举的第一行必须是枚举项,所有其它的变量和方法都必须在枚举项后面 

3) 枚举类可以定义抽象方法,但没枚举项必须重写所有抽象方法 

4)可以在switch中使用枚举,它的使用方法如下:

 1switch(EnumTest.ONE){
2
3case ONE:
4
5break;
6
7case TWO:
8
9break;
10
11}

 

 


 

觉得本文对你有帮助?请分享给更多人

关注「编程无界」,提升装逼技能