Java enum 枚举类型

2,015 阅读4分钟

定义

枚举类型(enum type)是指由一组固定的常量组成合法的类型。Java 中由关键字enum来定义一个枚举类型。

Java 枚举类型的定义

public enum Season {
    SPRING, SUMMER, AUTUMN, WINER
}

上面的代码说明创建了Season枚举类型,并声明了四个枚举值,分别是SPRING, SUMMER, AUTUMN, WINER,实际上这段代码是调用了4次Enum(String name, int ordinal),也就是:
  SPRING = new Enum("SPRING",0);
  SUMMER = new Enum("SUMMER",0);
  AUTUMN = new Enum("AUTUMN",0);
  WINER = new Enum("WINER",0);

枚举类型特点

  • 不可以在enum 类型中指定枚举项的初始值,如果需要指定枚举项的初始值则重写枚举类型的构造函数。
  • 枚举类型不支持 public 和 protected 修饰符的构造方法,因此构造函数一定要是 private 或 friendly 的。
  • enum 类型可以定义新的变量。
  • enum 类型可以定义新的方法。
  • enum 类型可以实现一个或多个接口。
  • 定义 enum 类型时候,如果是简单类型,那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号';'隔开,不能用逗号或空格
  • 可以定义根据具体枚举值而相异的类。
  • 由于 enum 类型的值实际上是通过运行期构造出对象来表示的。这是因为在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类,也就是说通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。

反编译Season.class

final class Season extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Season[] values()
    {
        return (Season[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Season valueOf(String s)
    {
        return (Season)Enum.valueOf(com/zeroXuan/enumdemo/Season, s);
    }
    //私有构造函数
    private Season(String s, int i)
    {
        super(s, i);
    }
     //前面定义的4种枚举实例
    public static final Season SPRING;
    public static final Season SUMMER;
    public static final Season AUTUMN;
    public static final Season WINER;
    private static final Season $VALUES[];

    static 
    {    
        //实例化枚举实例
        SPRING = new Season("SPRING", 0);
        SUMMER = new Season("SUMMER", 1);
        AUTUMN = new Season("AUTUMN", 2);
        WINER = new Season("WINER", 3);
        $VALUES = (new Season[] {
            SPRING, SUMMER, AUTUMN, WINER
        });
    }
}

用法

用法一:常量

public enum Color {  
  RED, GREEN, BLANK, YELLOW  
} 

用法二:switch

num Signal {  
    GREEN, YELLOW, RED  
}  
public class TrafficLight {  
    Signal color = Signal.RED;  
    public void change() {  
        switch (color) {  
        case RED:  
            color = Signal.GREEN;  
            break;  
        case YELLOW:  
            color = Signal.RED;  
            break;  
        case GREEN:  
            color = Signal.YELLOW;  
            break;  
        }  
    }  
}  

用法三:向枚举中添加新方法

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;  
    }  
}  

用法四:覆盖枚举的方法

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;  
    }  
    //覆盖方法  
    @Override  
    public String toString() {  
        return this.index+"_"+this.name;  
    }  
}  

用法五:实现接口

ublic interface Behaviour {  
    void print();  
    String getInfo();  
}  
public enum Color implements Behaviour{  
    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;  
    }  
//接口方法  
    @Override  
    public String getInfo() {  
        return this.name;  
    }  
    //接口方法  
    @Override  
    public void print() {  
        System.out.println(this.index+":"+this.name);  
    }  
}  

用法六: 使用接口组织枚举

public interface Food {  
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}

用法七:单例模式的枚举类型实现

/**
 * Created by wuzejian on 2017/5/9.
 * 枚举单例
 */
public enum  SingletonEnum {
    INSTANCE;
    private String name;
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}

用法八:enum类中定义抽象方法

> 通过这种方式就可以轻而易举地定义每个枚举实例的不同行为方式。我们可能注意到,enum类的实例似乎表现出了多态的特性,可惜的是枚举类型的实例终究不能作为类型传递使用。
public enum EnumDemo3 {

    FIRST{
        @Override
        public String getInfo() {
            return "FIRST TIME";
        }
    },
    SECOND{
        @Override
        public String getInfo() {
            return "SECOND TIME";
        }
    }

    ;

    /**
     * 定义抽象方法
     * @return
     */
    public abstract String getInfo();

    //测试
    public static void main(String[] args){
        System.out.println("F:"+EnumDemo3.FIRST.getInfo());
        System.out.println("S:"+EnumDemo3.SECOND.getInfo());
        /**
         输出结果:
         F:FIRST TIME
         S:SECOND TIME
         */
    }
}

在enum 类型中使用接口还是抽象方法

  • 如果一个方法,每个枚举常量的方法实现都是一样的,那么最好使用接口,,只要在枚举中实现一个接口方法即可。
  • 如果每个常量的行为各异,变化大,那么使用抽象方法来做,较为合适。使用抽象方法,每个枚举中的常量都需要实现一遍抽象方法。