Java枚举学习

Java枚举学习

说明:作者才疏学浅,本文仅为作者学习笔记,如果帮助到后来者,不胜荣幸,另外本文参考了其他大佬的讲解和代码,链接在下方贴出
参考链接:
Java 枚举(enum) 详解7种常见的用法
参深入理解Java枚举类型(enum)

借助一个常见的枚举例子,了解一下枚举的基本概念

enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

枚举是什么

枚举是java5提供的新特性之一,我们可以在一定程度上把它理解成是“类”这种类型,但是它比“类”这种数据类型又多了一些约束,因此可以理解为枚举是一种特殊的类类型。通过javac命令可以看出,enum编译后的确可以得到class文件,由此证明,我们编写的枚举类经过编译后,编译器会帮我们生成一个与枚举相关的类。

枚举里面的东东是什么

上面说到,枚举可以理解成一种特殊的类类型。其中所定义的MONDAY等,这些量叫做枚举常量,其数据类型就是枚举类Day,也就是说,这些枚举常量其实就是相应的枚举类(此处是Day)的实例化对象而已,这里要注意这些实例化对象都是static final修饰的,即都是常量,不可以被改变。这里附上大佬将枚举类的class文件反编译得到的结果,应该可以更好地理解:

//反编译Day.class
final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

Enum类

从上面反编译的文件中我们可以看出,编译器为我们生成的枚举相关的类是继承于Enum这个类的,Enum是所有java枚举类型的公共基本类,它是一个抽象类。接下来学习一下这个类中的核心方法。

返回类型方法名称方法说明
Stringname()返回此枚举常量的名称,在其枚举声明中对其进行声明
StringtoString()返回枚举常量的名称,它包含在声明中
intordinal()返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)
intcompareTo(E o)比较此枚举与指定对象的顺序
booleanequals(Object other)当指定对象等于此枚举常量时,返回 true。
static<T extends Enum> T staticvalueOf(Class enumType, String name)返回带指定名称的指定枚举类型的枚举常量。
Class<?>getDeclaringClass()返回与此枚举常量的枚举类型相对应的 Class 对象

其中name和toString方法,可以得到枚举常量的名称,ordinal方法,可以返回枚举常量的序数,注意下标是从0开始,compare方法是比较两个枚举常量的序数大小,equals是枚举常量的比较。关于valueOf方法,可以根据枚举类型和名称返回指定的枚举常量,最后的getDeclaringClass方法后面学到再看。

values与valueOf

回过头再看反编译得到的代码,枚举相关的类继承了Enum这个抽象类之后,编译器又为其生成了一个values方法,并重载了继承而来的valueOf方法。valueOf方法的功能没有改变,依旧是返回相关的枚举常量,只不过这时候只需要传递常量的名称为参数即可,不需要指定哪个枚举类中的了。
而新生成的values方法也并不神秘,他是一个static方法,可以以数组形式返回枚举中所有的枚举常量。

 //例如
	Day[] ds=Day.values();
	Day day = Day.valueOf("MONDAY");

既然如此,那么问题来了,当枚举类型向上转型为Enum类型时,values方法就不能用了,那怎么获取所有的枚举常量呢?
哈哈哈,当然有解决办法啦,我们知道Java中所有的类都有一个共同的老大Class,枚举类型虽然是一种特殊的类类型,但是依然被Class所折服,在Class中,有一个专门为枚举类型准备的方法——getEnumConstants(),这个方法可以返回枚举的所有常量,而如果其不是枚举类型,则返回null。而且,我们还可以使用isEnum方法判断其是否为枚举类型,因此,大佬写出了如下代码:

Class<?> clasz = e.getDeclaringClass();
if(clasz.isEnum()) {
    Day[] dsz = (Day[]) clasz.getEnumConstants();
    System.out.println("dsz:"+Arrays.toString(dsz));
}
/**
   输出结果:
   dsz:[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
 */

通过这种方法,我们又可以获得所有的枚举常量啦。


经过上述学习,我们基本可以把枚举当成类去思考。下面记录枚举的常见用法:

1. 用枚举来表示类似含义的常量

//其实就是第一个例子
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

2. 用枚举作为switch-case的支持类型

switch可以支持int ,char ,和枚举


enum Signal {  
    GREEN, YELLOW, RED  
}  
public class TrafficLight {  
    Signal color = Signal.RED;  
    public void change() {  
        switch (color) {  
        case RED:  
           	//操作。。。
            break;  
        case YELLOW:  
            //操作。。。
            break;  
        case GREEN:  
            //操作。。。
            break;  
        }  
    }  
} 

3. 向枚举中添加新方法

我们知道,枚举常量是由编译器根据我们的定义生成的实例化对象,生成过程中使用的是默认的构造函数,其实,我们也可以自定义每个枚举类型的构造函数,例如:

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index; 
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    } 
    //普通方法
}

注意:各个枚举常量的构造方法必须写在最前面,用逗号分隔开,最后一个写分号。然后在下面可以定义枚举类的属性,构造方法和普通方法

4. 方法覆盖

上面已经说了,枚举会被编译器转变成相关的类,那么我们就可以重写其原有的方法,即方法覆盖,例如,重写toString()

public enum Color {  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index;  
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
    //覆盖方法  
    @Override  
    public String toString() {  
        return this.index+"_"+this.name;  
    }  
}  

5. 实现接口

枚举所生成的类,已经继承了Enum类,因此,我们只能通过接口来对枚举进行扩展

public interface Interface1{
	//......
}
public enum Day implements Interface1{
	//........
}

下面这两种用法还没有学,好像涉及到更难的东东,先行保留。。。。。

6. 用法六:使用接口组织枚举

7. 用法七:关于枚举集合的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值