Java中的枚举类

一、定义

     创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。

    在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的。例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的“数据集”。在java中如何更好的使用这些“数据集”呢?因此枚举便派上了用场,以下代码详细介绍了枚举的用法。

    (Thinking in Java)枚举就是可以将其中常量的值必然的限制在一个常量集的范围内。

                                可以使用import来导入enum类,这样就不用在此类中中再声明enum。

                                除了不能继承自一个enum,我们基本上可以将enum看做一个常规的类。

 

二、特性

    创建enum时,编译器会自动添加一些有用的特性:

  • 创建toString()方法,以便方便的显示某个enum实例的名字。
  • 创建ordinal()方法,表示某个enum常量的声明顺序,从零开始。
  • 创建static values()方法,用来按照enum常量的声明顺序,产生由这些常量值构成的数组。

 

三、常用方法

  • int compareTo(E o)        // 比较此枚举与指定对象O的顺序。
  • class<E> getDeclaringClass()      // 返回此枚举对象所属的枚举类型。
  • String name()         // 返回此枚举常量的名称,在其枚举声明中对其进行声明。
  • int ordinal()       //  返回此枚举常量的声明顺序,从0开始。
public class Test {
    public static void main(String[] args) {
        EnumTest test = EnumTest.TUE;
         
        //compareTo(E o)
        switch (test.compareTo(EnumTest.MON)) {
        case -1:
            System.out.println("TUE 在 MON 之前");
            break;
        case 1:
            System.out.println("TUE 在 MON 之后");
            break;
        case 0:
            System.out.println("TUE 与 MON 在同一位置");
            break;
        }
         
        //getDeclaringClass()
        System.out.println("getDeclaringClass(): " + test.getDeclaringClass().getName());
         
        //name() 和  toString()
        System.out.println("name(): " + test.name());
        System.out.println("toString(): " + test.toString());
         
        //ordinal(), 返回值是从 0 开始
        System.out.println("ordinal(): " + test.ordinal());
    }
}

输出结果:

TUE 在 MON 之后
getDeclaringClass(): com.hmw.test.EnumTest
name(): TUE
toString(): TUE
ordinal(): 1

 

四、用法

  • 最一般的enum声明
public enum Season {
    //常量,所以大写,多词用下划线分割
    SPRING, SUMMER, FALL, WINTER
}
  • 带有构造器的enum声明
public enum Gender{
        //通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错
        //赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错
        MAN("Man"), WOMEN("Women");
        
        private final String value;

        //构造器默认也只能是private, 从而保证构造函数只能在内部使用
        Gender(String value) {
            this.value = value;
        }
        
        public String getValue() {
            return value;
        }

        public static void main(String[] args) {
             for(Gender gen : Gender.values())
                print(gen + ":" + gen.getValue());
        }
    }

输出结果:

MEN:Men
WOMEN:Women

构造器默认是private,我们只能在enum定义内部使用其构造器创建enum实例。一旦enum定义结束,编译器就不允许我们使用构造器来创建实例了。

  • 遍历
//方法1:enum类.values()返回枚举类型数组
for(Gender gen : Gender.values()) {
    print(gen.toString());
}

//方法2:class类中有一个方法,可以返回枚举类型数组
for(Gender gen : gen.getClass().getEnumConstants()) {
    print(gen.toString());
}
  • 覆盖enum的方法

        重写toString()方法,为我们提供了另一种方式来为枚举类型实例生成不同的字符串描述信息。

public enum Season {
    SPRING, SUMMER, FALL, WINTER;
    public String toString() {
         String id = name();
         String lower = id.substring(1).toLowerCase();
         return id.CharAt(0) + lower;
    }
    public static void main(String[] args) {
        for(Season se : values())
            print(se);
    }
}
/*
output:
Spring
Summer
Fall
Winter
*/
  • switch语句中的enum

一般来说,switch中使用整数值,而枚举天生具有整数值的次序,即ordinal(),所以在enum中很好用。

enum Signal {
        GREEN, YELLOW, RED
    }

    public class TrafficLight {
        Signal color = Signal.RED;

        public void change() {
            switch (color) {
            // 不必使用Signal.RED修饰,直接写即可
            case RED:
                color = Signal.GREEN;
                break;
            case YELLOW:
                color = Signal.RED;
                break;
            case GREEN:
                color = Signal.YELLOW;
                break;
            }
        }
    }
  • 在enum中定义普通方法
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;
        }
    }
  • 在enum中随机选取 
public class Enums {

    private static Random rand = new Random(47);
    // <T extends Enum<T>>表示T是一个enum实例。Class<T>作为参数,可以利用利用Class类的getEnumConstants()
    // 得到枚举类内的元素,以枚举类型的数组形式返回。
    public static <T extends Enum<T>> T random(Class<T> ec) {
        return random(ec.getEnumConstants());
    }
    // 重载random方法,以枚举类型的数组形式T[]作为参数,随机选取,返回类型正是一个enum类型
    public static <T> T random(T[] values) {
        return values[rand.nextInt(values.length)];    
    }
}

使用例子:

public enum Activity {
    RUNNING,JUMPING,FLYING
}
// enum的class做参数
public class RandomTest {
    for (int i = 0; i < 7; i++){
        System.out.println(Enums.random(Activity.class) + " ");
    }
}

 

五、使用接口组织枚举

  • 扩展原enum中的元素。
  • 将enum中的元素进行分组。 

 

你可能感兴趣的:(Java中的枚举类)