《Java从小白到大牛》第15章:枚举类

第15章 枚举类

Java 5之前没有提供枚举类型,尽管可以通过声明静态常量(final static变量)替代枚举,但是仍然很多Java程序员期待能有类似其他语言中的枚举类型。Java 5之后提供了枚举类型,Java枚举类型本质上是一种继承java.lang.Enum类,是引用数据类型,因此也称为“枚举类”。本章介绍Java枚举类。

15.1 枚举概述

在C和Objective-C等其他语言中,枚举用来管理一组相关常量的集合,使用枚举可以提高程序的可读性,使代码更清晰且更易于维护。
在Java 5之前没有提供枚举类型,可以通过声明静态常量(final static变量)替代枚举常量,例如想声明一组常量表示一周中的5个工作日,那么Java 5之前实现代码如下:
//WeekDays.java文件
package com.a51work6;

public interface WeekDays{
// 枚举常量列表
int MONDAY = 0; //星期一
int TUESDAY = 1; //星期二
int WEDNESDAY = 2; //星期三
int THURSDAY = 3; //星期四
int FRIDAY =4; //星期五
}
通常在接口中声明一组静态常量,当然也可以在一般类中声明一组静态常量。这些常量往往都是int类型,这是为了以后方便使用switch语句进行判断。
调用代码如下:
//HelloWorld.java文件
package com.a51work6;

public class HelloWorld {

        public static void main(String[] args)
        
            //day工作日变量
            int day = WeekDays.FRIDAY;    ①      
                    
            switch (day) {
            case WeekDays.MONDAY:
                System.out.println("星期一");
                break;
            case WeekDays.TUESDAY:
                System.out.println("星期二");
                break;
            case WeekDays.WEDNESDAY:
                System.out.println("星期三");
               break;
            case WeekDays.THURSDAY:
                System.out.println("星期四");
                break;
            case WeekDays.FRIDAY:
                System.out.println("星期五");
                break;
            }
        }

}
从上述代码中直接使用这些常量。但这种方式还存在一些问题:
1.类型不安全。代码第①行是声明工作日变量day,day是整数类型,程序执行过程中很有可能给day变量传入一个任意的整数值,可能导致程序出现错误。
2.程序不方便调试。在程序调试时,如果通过日志输出day值,那么只能看到0~4之间的数值,程序员需要比较这些数值代表的含义,才能知道输出的结果是什么。
枚举类型可以避免直接使用常量所导致的问题。Java 5之后可以使用枚举类型了,Java中枚举类型的作用已经不仅仅是定义一组常量提高程序的可读性了,还具有如下特性:
1.Java枚举类型是一种类,是引用类型,具有了面向对象特性,可以添加方法和成员变量等。
2. Java枚举类型父类是java.lang.Enum,不需要显式声明。
3. Java枚举类型可以实现接口,与类实现接口类似。
4.Java枚举类型不能被继承,不存在子类。

15.2 枚举类声明

先来看Java中的枚举类声明。Java中是使用enum关键词声明枚举类,具体定义放在一对大括号内,枚举的语法格式如下:
[public] enum 枚举名 {
枚举常量列表
}
enum前面的修饰符是[public]表示public或省略。public是公有访问级别,可以在任何地方访问。省略是默认访问级别,只能在当前包中访问。
“枚举名”是该枚举类的名称。它首先应该是有效的标识符,其次应该遵守Java命名规范。它应该是一个名称,如果采用英文单词命名,首字母应该大写,且应尽量用一个英文单词。“枚举常量列表”是枚举的核心,它由一组相关常量组成。

15.2.1 最简单形式的枚举类
如果采用枚举类来表示工作日,最简单枚举类WeekDays具体代码如下:
//WeekDays.java文件
package com.a51work6;

public enum WeekDays {
// 枚举常量列表
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
}
在枚举类WeekDays中定义了5个常量,使用枚举类WeekDays代码如下:
//HelloWorld.java文件
package com.a51work6;

public class HelloWorld {

        public static void main(String[] args) {
            // day工作日变量
            WeekDays day = WeekDays.FRIDAY;       ①
            System.out.println(day);                             ②      
            
            switch (day) {                                             ③
            case MONDAY:                                          ④
                System.out.println("星期一");
                break;
            case TUESDAY:
                System.out.println("星期二");
                break;
            case WEDNESDAY:
                System.out.println("星期三");
                break;
            case THURSDAY:
                System.out.println("星期四");
                break;
            default: //case FRIDAY:                             ⑤
                System.out.println("星期五");        
           }
        }

}
输出结果:
FRIDAY
星期五
上述代码第①行是声明工作日变量day,day是WeekDays枚举类型,取值是WeekDays.FRIDAY,是枚举类中定义的枚举常量。day = WeekDays.FRIDAY赋值过程中实例化WeekDays枚举类对象,并初始化为WeekDays.FRIDAY。注意赋值表达式是“枚举类型名.枚举常量”的形式。
代码第②行day对象日志输出结果不是整数,而是FRIDAY。
枚举类与switch语句能够很好地配合使用,代码第③行switch表达式直接使用day枚举对象,case常量直接使用枚举常量,见代码第④行,而且不需要枚举类名作为前缀,使用起来比较简洁。
《Java从小白到大牛》第15章:枚举类_第1张图片
15.2.2 枚举类中成员变量和成员方法
枚举类可以像类一样包含成员变量和成员方法,成员变量可以是实例变量也可以是静态变量,成员方法可以是实例方法,也可以是静态方法,但不能是抽象方法。
示例代码如下:
//WeekDays.java文件
package com.a51work6;

public enum WeekDays {
// 枚举常量列表
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY; ①

        // 实例变量
        private String name;
        private int index;
        
        // 静态变量
        private static int staticVar = 100;
        
        // 覆盖父类中的toString()方法
        @Override
        public String toString() {                                                                   ②
            StringBuilder sb = new StringBuilder();
            sb.append(name);
            sb.append('-');
            sb.append(index);
            return sb.toString();
        }
        
        // 实例方法
        public String getInfo() {
            // 调用父类中toString()方法
            return super.toString();
        }
        
        // 静态方法
        public static int getStaticVar() {
            return staticVar;
        }

}
上述代码第①行在枚举类WeekDays中添加了一些成员变量和成员方法,这些方法还可以覆盖枚举父类(java.lang.Enum)中的方法,见代码第②行的toString()方法。
添加的其他成员的枚举类需要注意,“枚举常量列表”语句必须是枚举类中的第一行代码。而且“枚举常量列表”语句后面要加分号(;)表示语句的结束,见代码第①行所示。
使用枚举类WeekDays代码如下:
//HelloWorld.java文件
package com.a51work6;

public class HelloWorld {

        public static void main(String[] args) {
            // day工作日变量
            WeekDays day = WeekDays.FRIDAY;          
            
            //打印day默认调用枚举toString()方法
            System.out.println(day);
            //调用枚举实例方法
            System.out.println(day.getInfo());
            //调用枚举静态方法
            System.out.println(WeekDays.getStaticVar());    
                   
        }

}
上述代码比较简单这里不再赘述。

15.2.3 枚举类构造方法
在15.2.2节示例中实例变量name和index,都是没有初始化,在类中成员变量的初始化是通过构造方法实现的,而在枚举类中也是通过构造方法初始化成员变量的。
为15.2.2节示例添加构造方法,代码如下:
//WeekDays.java文件
package com.a51work6;

public enum WeekDays {
// 枚举常量列表
MONDAY(“星期一”, 0), TUESDAY(“星期二”, 1), WEDNESDAY(“星期三”, 2),
THURSDAY(“星期四”, 3), FRIDAY(“星期五”, 4); ①

        // 实例变量
        private String name;
        private int index;
        
        // 静态变量
        private static int staticVar = 100;
        
        private WeekDays(String name, int index) {                                       ②
            this.name = name;
            this.index = index;
        }
        
        // 覆盖父类中的toString()方法
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(name);
            sb.append('-');
            sb.append(index);
            return sb.toString();
        }
        
        // 实例方法
        public String getInfo() {
            // 调用父类中toString()方法
            return super.toString();
        }
        
        // 静态方法
        public static int getStaticVar() {
            return staticVar;
        }

}
上述代码第②行是添加的构造方法,注意枚举类的中的构造方法只能是私有访问级别,构造方法可以省略private关键字,但它仍然是私有的构造方法。这也说明了枚举类不允许在外部创建对象。
在这里插入图片描述
一旦添加了有参数的构造方法,那么“枚举常量列表”也需要修改,见代码第①行,每一个枚举常量都是一个实例,都会调用构造方法进行初始化成员变量,(“星期一”, 0)是调用构造方法。

15.3 枚举常用方法

所有枚举类都继承java.lang.Enum类,Enum中定义了一些枚举中常用的方法:
o int ordinal():返回枚举常量的顺序。这个顺序根据枚举常量声明的顺序而定,顺序从零开始。
o 枚举类型[] values():静态方法,返回一个包含全部枚举常量的数组。
o 枚举类型 valueOf(String str):静态方法,str是枚举常量对应的字符串,返回一个包含枚举类型实例。
WeekDays枚举类代码如下:
//WeekDays.java文件
package com.a51work6;

public enum WeekDays {
// 枚举常量列表
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
}
使用枚举常用方法示例代码如下:
//HelloWorld.java文件
package com.a51work6;

public class HelloWorld {

        public static void main(String[] args) {
        
            // 返回一个包含全部枚举常量的数组
            WeekDays[] allValues = WeekDays.values();                        ①
            // 遍历枚举常量数值
            for (WeekDays value : allValues) {
                System.out.printf("%d - %s\n",value.ordinal(), value);       ②
            }
            
            // 创建WeekDays对象
            WeekDays day1 = WeekDays.FRIDAY;
            WeekDays day2 = WeekDays.valueOf("FRIDAY");               ③
            
            System.out.println(day1 == WeekDays.FRIDAY);                  ④
            System.out.println(day1.equals(WeekDays.FRIDAY));          ⑤
            System.out.println(day1 == day2);                                       ⑥
            
        }

}
上述代码第①行是通过values方法获得所有枚举常量的数组,代码第②行是获得枚举常量value,其中value.ordinal()获得当前枚举常量的顺序。
代码第③行是通过valueOf方法获得枚举对象WeekDays.FRIDAY,参数是枚举常量对应的字符串。
代码第④行~第⑥行是比较枚举对象,它们比较的结果都是true。
《Java从小白到大牛》第15章:枚举类_第2张图片

本章小结

通过对本章的学习,读者可以了解到Java中枚举的作用、特点和常用方法。重点是声明和使用枚举类。

你可能感兴趣的:(《Java从小白到大牛》第15章:枚举类)