Java枚举类型

    |     2017年8月10日   |   Java 语法基础   |     0 条评论   |    1401

Java 从 JDK 1.5 才有枚举,和泛型一样是后来补上的特性。晚加的语法要向后兼容,编译器会帮源码做很多事(类型擦除、桥接方法、foreach、装箱拆箱),术语叫语法糖。枚举也走这条路:表面是 enum,底下是 java.lang.Enum 子类。

1.5 增加了抽象类 java.lang.Enum 当所有枚举的基类,并提供 EnumSet / EnumMap。项目里更推荐用枚举常量,而不是接口常量或类常量。

一、枚举类型

日常开发常定义常量;《Effective Java》建议用枚举替换,可读性和约束都更好。enum 隐含继承 Enum(抽象类),符合 Class Enum<E> 模式。每个枚举值都会进 protected Enum(String name, int ordinal):名字变成字符串,ordinal 是声明顺序。

public enum Week {

    MON, TUE, WED, THU, FRI, SAT, SUN;

}

上面实际相当于调了 7 次构造:MON 的 ordinal 是 0,TUE 是 1,以此类推。

用法 做什么
常量 把相关常量收进一个类型,还自带方法
switch 1.6 前 switch 只支持 int/char/enum,可读性更好
加方法 实例列表后加分号,且必须先写枚举实例
覆盖 / 接口 / 组织 可 toString、实现接口、用接口分组;不能再继承别的类
集合 EnumSet 不重复;EnumMap 的 key 必须是枚举

用法一:常量

1.5 之前只能 public static final。现在可以把一组常量收进枚举:

public enum Color {

  RED, GREEN, BLANK, YELLOW

}
Color color = Color.RED;   //color -> Red;

用法二:switch

enum 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 class Test {

    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;

        }

    }

    public static void main(String[] args) {

        System.out.println(Color.RED.toString());

    }

}

用法五:实现接口

枚举已经继承 Enum,Java 又不支持多继承,所以不能再 extends 别的类,但可以实现接口。

public 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

        }

    }

用法七:EnumSet 与 EnumMap

/**

     *

     * 演示枚举类型的遍历

     */

    private static void testTraversalEnum() {

        Light[] allLight = Light.values();

        for (Light aLight : allLight) {

            System.out.println("当前灯name:" + aLight.name());

            System.out.println("当前灯ordinal:" + aLight.ordinal());

            System.out.println("当前灯:" + aLight);

        }

    }

    /**

     *

     * 演示EnumMap的使用,EnumMap跟HashMap的使用差不多,只不过key要是枚举类型

     */

    private static void testEnumMap() {

        // 1.演示定义EnumMap对象,EnumMap对象的构造函数需要参数传入,默认是key的类的类型

        EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>(

        Light.class);

        currEnumMap.put(Light.RED, "红灯");

        currEnumMap.put(Light.GREEN, "绿灯");

        currEnumMap.put(Light.YELLOW, "黄灯");

        // 2.遍历对象

        for (Light aLight : Light.values()) {

            System.out.println("[key=" + aLight.name() + ",value="

            + currEnumMap.get(aLight) + "]");

        }

    }

    /**

     *

     * 演示EnumSet如何使用,EnumSet是一个抽象类,获取一个类型的枚举类型内容<BR/>

     *

     * 可以使用allOf方法

     */

    private static void testEnumSet() {

        EnumSet<Light> currEnumSet = EnumSet.allOf(Light.class);

        for (Light aLightSetElement : currEnumSet) {

            System.out.println("当前EnumSet中数据为:" + aLightSetElement);

        }

    }

}

更细的实现原理:java 枚举类型的实现原理。

一句话总结:枚举是 JDK 1.5 的语法糖,编译后仍是 Enum 子类;用它收拢常量、进 switch、加方法或实现接口,集合侧优先 EnumSet/EnumMap。

转载请注明来源:Java枚举类型
本文链接地址:https://ai.zhousir.top/?p=2116
回复 取消