枚举(enum)类型

关键字enum 可以将一组具名的值的有限集合创建一种新的类型,而这些具名的值可以作为常规的程序使用。创建enum 时,编译器会为你生成一个相关的类,这个类继承自java.lang.Enum 。下面是一个例子演示了一些Enum 提供的一些功能。

package com.jas.enumtest;

enum Animal{CAT,DOG,SHEEP}

public class EnumClass {
    public static void main(String[] args) {

        for(Animal animal : Animal.values()){
            System.out.println(animal + " oridinal:" + animal.ordinal());
            System.out.print(animal.compareTo(Animal.DOG) + " ");
            System.out.print(animal.equals(Animal.DOG) + " ");
            System.out.println(animal == Animal.DOG);
            System.out.println(animal.getDeclaringClass());
            System.out.println(animal.name());
            System.out.println("--------分割线----------");
        }

        for(String str : "DOG,CAT,SHEEP".split(",")){
            Animal animal = Animal.valueOf(Animal.class,str);
            System.out.print(animal + " ");
        }
    }
}

输出:
CAT oridinal:0
-1 false false
class com.jas.enumtest.Animal
CAT
——–分割线———-
DOG oridinal:1
0 true true
class com.jas.enumtest.Animal
DOG
——–分割线———-
SHEEP oridinal:2
1 false false
class com.jas.enumtest.Animal
SHEEP
——–分割线———-
DOG CAT SHEEP

      ordinal() 方法返回一个int 类型的值,这个值是enum 在实例中声明的顺序,从0 开始。可以使用 == 来比较enum 实例,编译器会自动为你提供equals() 方法与 hashCode() 方法。Enum 类实现了Comparable 接口,所以你可以使用compareTo() 方法。同时Enum 类还实现了Serializable 接口。
      getDeclaringClass() 方法返回其所属的类。
      name 方法返回enum 实例声明时的名字,这与toString 方法返回的值相同。valueOf() 是在Enum 中定义的static 方法,它可以根据给定的名字返回相应的enum 实例,如果不存在给定名字的实例,就会抛出异常。

覆盖enum 的方法
      当我们想要覆盖enum 中的方法时,我们会发现,它就只有一个方法toString(),当我们覆盖它时与覆盖一般的类的方法没有区别。

enum Animal{
    CAT,DOG,SHEEP;

    @Override
    public String toString() {
        String id = name();
        String lower = id.substring(1).toLowerCase();

        return id.charAt(0) + lower;
    }
}
public class EnumClass {
    public static void main(String[] args) {

        for(Animal animal : Animal.values())
            System.out.print(animal + " ");
    }
}

输出
Cat Dog Sheep

向enum 中添加方法
      除了不能继承一个enum 之外,我们基本上可以将enum 看作是一个常规的类。这也意味着enum 拥有自己的构造函数,以及我们可以向enum 中添加方法。它甚至是可以拥有main() 方法。这里我们通过一个方法返回一个枚举类型的描述不再仅仅是一个toString() 类型的实现。

enum Animal{
    // private String description; 这是不允许的
    CAT("喵喵喵~"),
    DOG("汪汪汪~"),
    SHEEP("咩咩咩~");

    private String description;
    private Animal(String description){
        this.description = description;
    }
    public String getDescription(){
        return description;
    }
}
public class EnumClass {
    public static void main(String[] args) {

        for(Animal animal : Animal.values())
            System.out.println(animal + " : " + animal.getDescription());
    }
}

输出:
CAT : 喵喵喵~
DOG : 汪汪汪~
SHEEP : 咩咩咩~

      需要注意的是:如果我们打算自定义方法,那么必须在enum 徐磊实例的后面添加一个分号。同时Java 要求你必须先定义enum 实例,就像上面这样我们打算在定义enum 实例之前定义description 但是却得到一个编译器的错误提示。enum 中的构造函数与方法与普通的类没有任何区别,除了有少量的限制enum 可以说就是一个类。所以我们可以使用enum 做许多额外的事。

switch 语句中的 enum
      一般来说,在switch 语句中 只能使用整数值,而枚举天生就具备整数值的次序,并且可以通过ordinal() 方法获得其在enum 中的顺序,因此我们可以在switch 中使用枚举。

enum Singal{GREEN, YELLOW, RED}

public class TrafficLight {
    Singal color = Singal.RED;

    public void change(){
        switch (color){
            case RED: color = Singal.GREEN;
                break;
            case GREEN: color = Singal.YELLOW;
                break;
            case YELLOW: color = Singal.RED;
                break;
        }
    }
    public String toString(){
        return "The traffic light is : " + color;
    }
    public static void main(String[] args) {

        TrafficLight light = new TrafficLight();
        for (int i = 0; i < 4; i++) {
            System.out.println(light.toString());
            light.change();
        }
    }
}

输出:
The traffic light is : RED
The traffic light is : GREEN
The traffic light is : YELLOW
The traffic light is : RED

values() 的神秘之处
      我们知道编译器为我们创建的enum 都继承自Enum 类。但是如果你去查看Enum 类就会发现,它并没有values() 方法。但是我们在上面确实使用了这个方法,这是为什么呢?下面我们使用反射机制来查看其中的原因。

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.TreeSet;

enum Explore{HERE,THERE}
public class Reflection {
    public static Set analyze(Class enumClass){
        Set set = new TreeSet<>();

        System.out.println("----- Analyzing " + enumClass + " -----");
        for(Type type : enumClass.getGenericInterfaces())
            System.out.println("genericInterface : " + type);
        System.out.println("superClass : " + enumClass.getSuperclass());
        for(Method method : enumClass.getMethods())
            set.add(method.getName());

        System.out.println("----- end -----");
        System.out.println();
        return set;
    }

    public static void main(String[] args) {

        Set exploreMethods = analyze(Explore.class);
        Set enumMethods = analyze(Enum.class);

        System.out.println("exploreMethods : " + exploreMethods);
        System.out.println("enumMethods : " + enumMethods);
        System.out.println("exploreMethods.containsAll(enumMethods): " + exploreMethods.containsAll(enumMethods));
        System.out.println("exploreMethods.removeAll(enumMethods): " + exploreMethods.removeAll(enumMethods));
        System.out.println("exploreMethods : " + exploreMethods);
    }
}

—– Analyzing class com.jas.enumtest.Explore —–
superClass : class java.lang.Enum
—– end —–

—– Analyzing class java.lang.Enum —–
genericInterface : java.lang.Comparable
genericInterface : interface java.io.Serializable
superClass : class java.lang.Object
—– end —–

exploreMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
enumMethods : [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
exploreMethods.containsAll(enumMethods): true
exploreMethods.removeAll(enumMethods): true
exploreMethods : [values]

      答案就是values() 方法是由编译器添加的static 方法。其实这个过程中还未其添加了valueOf() 方法。但是Enum 中明明已经有了valueOf() 方法,为什么编译器还会为其添加这个方法呢?Enum 中的valueOf() 方法需要传递进来两个参数,但是新增的这个方法只需要传递进来一个参数。

                                                                                                            参考书籍:
                                                                                                                《Java 编程思想》Bruce Eckel 著 陈昊鹏 译

你可能感兴趣的:(Java,基础)