枚举类的使用方法

一、理解枚举类型

枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。下面先来看看如何写一个枚举?

二、枚举的定义语法

在没有枚举类型时定义常量常见的方式
    public class DayDemo {
        public static final int MONDAY =1;
        public static final int TUESDAY=2;
        public static final int WEDNESDAY=3;
        public static final int THURSDAY=4;
        public static final int FRIDAY=5;
        public static final int SATURDAY=6;
        public static final int SUNDAY=7;
    }

上述的常量定义常量的方式称为int枚举模式,这样的定义方式并没有什么错,但它存在许多不足,如在类型安全和使用方便性上并没有多少好处,如果存在定义int值相同的变量,容易混淆,因此这种方式在枚举出现后并不提倡,现在我们利用枚举类型来重新定义上述的常量,定义周一到周日的常量
//枚举类型,使用关键字enum

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

相当简洁,在定义枚举类型时我们使用的关键字是enum,与class关键字类似,只不过前者是定义枚举类型,后者是定义类类型。

枚举类型Day中分别定义了从周一到周日的值,这里要注意,值一般是大写的字母,多个值之间以逗号分隔。同时我们应该知道的是枚举类型可以像类(class)类型一样,定义为一个单独的文件,当然也可以定义在其他类内部,更重要的是枚举常量在类型安全性和便捷性都很有保证,如果出现类型问题编译器也会提示我们改进,但务必记住枚举表示的类型其取值是必须有限的,也就是说每个值都是可以枚举出来的,比如上述描述的一周共有七天。

以上是写法,写好后该如何使用呢?如下:

    public class EnumDemo {
        public static void main(String[] args){
            //直接引用
            Day day =Day.MONDAY;
        }
    }

就像上述代码那样,直接引用枚举的值即可,这便是枚举类型的最简单模型。

三、为什么可以这样用,看看枚举实现原理就知道了

我们大概了解了枚举类型的定义与简单使用后,现在有必要来了解一下枚举类型的基本实现原理。实际上在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类,也就是说通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。我们可以看看反编译的结果!

结论:从反编译的代码可以看出编译器确实帮助我们生成了一个Day类而且该类继承自java.lang.Enum类,该类是一个抽象类,除此之外,编译器还帮助我们生成了7个Day类型的实例对象分别对应枚举中定义的7个日期。还为我们生成了两个静态方法,分别是values()和 valueOf(),到此我们也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好常量的对应实例对象,如上述的MONDAY枚举类型对应public static final Day MONDAY;

四、编译器生成的Values方法与ValueOf方法

values()方法和valueOf(String name)方法是编译器生成的static方法,后面我们自己定义的枚举类的父类Enum的分析中,在Enum类中并没出现values()方法,但valueOf()方法还是有出现的,只不过编译器生成的valueOf()方法需传递一个name参数,而Enum自带的静态方法valueOf()则需要传递两个方法,从前面反编译后的代码可以看出,编译器生成的valueOf方法最终还是调用了Enum类的valueOf方法,下面通过代码来演示这两个方法的作用:
    Day[] days2 = Day.values();
    System.out.println("day2:"+Arrays.toString(days2));
    Day day = Day.valueOf("MONDAY");
    System.out.println("day:"+day);

输出结果:

  day2:[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
  day:MONDAY

从结果可知道,values()方法的作用就是获取枚举类中的所有变量,并作为数组返回,而valueOf(String name)方法与Enum类中的valueOf方法的作用类似根据名称获取枚举变量,只不过编译器生成的valueOf方法更简洁些只需传递一个参数。

五、Enum抽象类常见方法

Enum是所有 Java 语言枚举类型的公共基本类(注意Enum是抽象类),以下是它的常见方法:

在这里插入图片描述

ordinal()方法,该方法获取的是枚举变量在枚举类中声明的顺序,下标从0开始,如日期中的MONDAY在第一个位置,那么MONDAY的ordinal值就是0,如果MONDAY的声明位置发生变化,那么ordinal方法获取到的值也随之变化,注意在大多数情况下我们都不应该首先使用该方法,毕竟它总是变幻莫测的。

compareTo(E o)方法则是比较枚举的大小,注意其内部实现是根据每个枚举的ordinal值大小进行比较的。

name()方法与toString()几乎是等同的,都是输出变量的字符串形式。

valueOf(Class enumType, String name)方法则是根据枚举类的Class对象和枚举名称获取枚举常量,注意该方法是静态的。

下面的代码演示了上述方法:

    public class EnumDemo {
        public static void main(String[] args){
            //创建枚举数组
            Day[] days=new Day[]{Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY,
                    Day.THURSDAY, Day.FRIDAY, Day.SATURDAY, Day.SUNDAY};
        for (int i = 0; i <days.length ; i++) {
            System.out.println("day["+i+"].ordinal():"+days[i].ordinal());
        }

        System.out.println("-------------------------------------");
        //通过compareTo方法比较,实际上其内部是通过ordinal()值比较的
        System.out.println("days[0].compareTo(days[1]):"+days[0].compareTo(days[1]));
        System.out.println("days[0].compareTo(days[1]):"+days[0].compareTo(days[2]));

        //获取该枚举对象的Class对象引用,当然也可以通过getClass方法
        Class<?> clazz = days[0].getDeclaringClass();
        System.out.println("clazz:"+clazz);

        System.out.println("-------------------------------------");

        //name()
        System.out.println("days[0].name():"+days[0].name());
        System.out.println("days[1].name():"+days[1].name());

        System.out.println("-------------------------------------");

        System.out.println("days[0].toString():"+days[0].toString());
        System.out.println("days[1].toString():"+days[1].toString());
       
        System.out.println("-------------------------------------");

        Day d=Enum.valueOf(Day.class,days[0].name());
        Day d2=Day.valueOf(Day.class,days[0].name());
        System.out.println("d:"+d);
        System.out.println("d2:"+d2);
    }

六、枚举的进阶用法

向enum类添加方法与自定义属性和构造函数 重新定义一个日期枚举类,带有desc成员变量描述该日期的对于中文描述,同时定义一个getDesc方法,返回中文描述内容,自定义私有构造函数,在声明枚举实例时传入对应的中文描述,代码如下:
    public enum Day2 {
        MONDAY("星期一",1),
        TUESDAY("星期二",2),
        WEDNESDAY("星期三",3),
        THURSDAY("星期四",4),
        FRIDAY("星期五",5),
        SATURDAY("星期六",6),
        SUNDAY("星期日",7);//记住要用分号结束

    private String desc;//文字描述
    private Integer code; //对应的代码

    /**
     * 私有构造,防止被外部调用
     * @param desc
     */
    private Day2(String desc,Integer code){
        this.desc=desc;
     this.code=code;
        }
    /**
     * 定义方法,返回描述,跟常规类的定义没区别
     * @return
     */
    public String getDesc(){
        return desc;
    }

     /**
         * 定义方法,返回代码,跟常规类的定义没区别
         * @return
         */
        public int getCode(){
            return code;
        }
    public static void main(String[] args){
        for (Day2 day:Day2.values()) {
            System.out.println("name:"+day.name()+
                    ",desc:"+day.getDesc());
        }
    }

输出结果:

  name:MONDAY,desc:星期一
  name:TUESDAY,desc:星期二
  name:WEDNESDAY,desc:星期三
  name:THURSDAY,desc:星期四
  name:FRIDAY,desc:星期五
  name:SATURDAY,desc:星期六
  name:SUNDAY,desc:星期日
在 Qt 中,可以方便地将枚举类enum class)作为方法参数传递。这种方式不仅有助于提高代码的可读性和安全性,还能够更好地组织相关的常量值。接下来我们将详细介绍如何定义和使用枚举类作为函数参数。 ### 定义枚举类 首先,在 C++11 及以上版本中推荐使用 `enum class` 来代替传统的 `enum` 关键字创建新的枚举类型。这样做是为了避免命名冲突并且提供更强的作用域限制。例如: ```cpp // 在头文件 (.h) 中声明一个名为 OperationMode 的枚举类 class MyClass { public: enum class OperationMode { Normal, Debug }; private slots: void setOperationMode(OperationMode mode); }; ``` 这里的 `MyClass::OperationMode` 就是一个作用域限定的枚举类型,其成员需要显式指明所属范围才能访问到。 ### 作为方法参数 当你想让某个方法接受特定类型的枚举值时,可以直接将其设置为该枚举类的对象即可。比如上面的例子中我们有一个私有的槽函数 `setOperationMode()`,它可以接收来自用户界面或者其他部分传入的操作模式信息: ```cpp void MyClass::setOperationMode(MyClass::OperationMode mode){ if(mode == MyClass::OperationMode::Debug){ qDebug()<<"现在处于调试模式"; } else { qDebug()<<"正常运行模式"; } } ``` 在这个实现里,我们检查了传进来的是哪种状态,并据此执行相应的动作。 此外,当从外部调用此类的方法时也需要指定正确的枚举值形式,像这样: ```cpp myObject->setOperationMode(MyClass::OperationMode::Normal); // 或者 myObject->setOperationMode(MyClass::OperationMode::Debug); ``` 这种方法使得 API 更加清晰易懂,同时也减少了错误输入的可能性,因为编译器会强制要求你只能传递有效的枚举值给目标方法
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值