深入学习 Java Enum 枚举类

Java 有两种方式定义新类型:类和接口。

对于大部分面向对象编程来说,这两种方法够了,但是对于一些特殊情况比如:想定义一个 Color 类,它只能有 Red、Green、Blue 3种值,其他的任何值都是非法的,这种情况就适用枚举简单方便。

所谓的枚举就是限制一个类的对象产生范围
在这里插入图片描述
其他知识可以参考:

一、基本概念

已经知道使用 eunm 关键字可以定义一个枚举,该关键字表示的是 java.lang.Enum类型,即使用 enum 声明的枚举类型就相当于定义一个类,此类默认继承 java.lang.Enum 类。
java.lang.Enum的定义:

public abstract  class Enum<E extends Enum<E>> extends Object
implements Comparable<E>,java.io.Serializable

从定义可看出该类实现了 Comparable 和 Serializable 接口,证明枚举可以使用比较器和序列化操作

枚举类的主要操作方法:
在这里插入图片描述
枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开

枚举其实就是特殊的常量类,切构造方法被默认强制是私有
例如:

枚举名字:DealStatusEnum
成员名称:SUCCESS / UNKNOWN_REASON

二、取得枚举的信息

在枚举类建立完成后,实际上都会为其调用枚举类中的构造方法,为其赋值。在 Enum 类的构造方法中的第一个参数 name 就是定义的枚举的名称,第二个参数 ordinal 则会从 0 开始依次进行编号,之后可以使用 Enum 类总提供的 name()ordinal() 方法取得名称和编号

enum Color{
    RED,GREEN,BLUE;//定义枚举的3个类型
}
public class Test{
    public static void main(String[] args) {
        for (Color c:Color.values()){//枚举.values() 表示得到全部枚举的内容
            System.out.println(c.ordinal() + "-->" + c.name());
        }
    }
}

在这里插入图片描述

三、为每一个枚举对象属性赋值

如果要为enum定义方法,那么必须在enum的最后一个实例尾部添加一个分号。此外,在enum中,必须先定义实例,不能将字段或方法定义在实例前面。否则,编译器会报错。

1. 通过构造方法为属性赋值

每个枚举类中都有其指定好的若干对象,当然每一个枚举对象中也可以包含多个属性,这些属性可以通过构造方法为其赋值

enum Color{
    RED("红色"),GREEN("绿色"),BLUE("蓝色");//定义枚举的3个类型
    private Color(String name){
        this.setName(name);
    }
    private String name;

    public String getName() {
        return name;
    }

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

}
public class Test{
    public static void main(String[] args) {
        for (Color c:Color.values()){//枚举.values() 表示得到全部枚举的内容
            System.out.println(c.ordinal() + "-->" + c.name() + c.getName());
        }
    }
}

程序中在定义的 Color 枚举类中设置了一个 name属性,并且通过构造方法设置 name 属性的内容。

因为 Color 中已经明确地写出了有一个参数的构造方法,所以在声明枚举内容时必须调用这个构造方法,这样在定义枚举内容时必须使用如下的语句形式:

RED("红色"),GREEN("绿色"),BLUE("蓝色");

或者:

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;  
    }  
    // 普通方法  
    public static String getName(int index) {  
        for (Color c : Color.values()) {  
            if (c.getIndex() == index) {  
                return c.name;  
            }  
        }  
        return null;  
    }  
    // get set 方法  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getIndex() {  
        return index;  
    }  
    public void setIndex(int index) {  
        this.index = index;  
    }  
}  

2. 通过 setter方法为属性赋值

也可以通过调用 setter() 方式为指定的属性赋值,但是这样必须明确每一个枚举类的对象,如果操作的对象时 RED,则名字应该为“红色”;如果操作的对象是GREEN,则名字应该为“绿色”等。

enum Color{
    RED,GREEN,BLUE;//定义枚举的3个类型
    private String name;
    public String getName(){
        return name;
    }

    public void setName(String name) {
        switch (this){
            case RED:{
                if ("红色".equals(name)){
                    this.name = name;
                }else System.out.println("设置内容错误。");
                break;
            }
            case GREEN:{
                if ("绿色".equals(name)){
                    this.name = name;
                }else System.out.println("设置内容错误。");
                break;
            }
            case BLUE:{
                if ("蓝色".equals(name)){
                    this.name = name;
                }else System.out.println("设置内容错误。");
                break;
            }
        }
    }
}
public class Root{
    public static void main(String[] args) {
        Color c = Color.BLUE;
        c.setName("兰色");//设置一个错误的名字
        c.setName("蓝色");//设置一个正确的名字
        System.out.println(c.getName());
    }
}

在这里插入图片描述
代码中首先通过枚举类取得了里面的一个对象,之后开始为期设置内容。

四、使用比较器

在 Enum 类的定义中已经实现好了 Comparable 接口,所以枚举类的内容本身是可以进行排序的,可以通过 TreeSet 进行枚举的排序操作

enum Color {
    RED, GREEN, BLUE;//定义枚举的3个类型
}

public class Root{
    public static void main(String[] args) {
        Set<Color> t = new TreeSet<Color>();//只能加入 Color 类型
        t.add(Color.GREEN);
        t.add(Color.BLUE);
        t.add(Color.RED);
        Iterator<Color> iter = t.iterator();//使用迭代输出
        while (iter.hasNext()) {
            System.out.print(iter.next() + "、");
        }
    }
}

在这里插入图片描述
这里加入的顺序和输出的信息不一致,证明已经被排序了,是使用Enum 类中的 ordinal 属性排序的

枚举类型对象之间的值比较,是可以使用==,直接来比较值,是否相等的,不是必须用equals

五、枚举的原理

实际上在使用关键字 enum 创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类,

也就是说通过关键字 enum 创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。

从反编译的代码可以看出编译器确实帮助我们生成了一个Color类而且该类继承自java.lang.Enum类,该类是一个抽象类,
除此之外,编译器还帮助我们生成了3个Color类型的实例对象分别对应枚举中定义的3个颜色。

还为我们生成了两个静态方法,分别是values()valueOf()

到此我们也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好常量的对应实例对象,如上述的RED枚举类型对应public static final Day RED

在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南淮北安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值