• Java Enum解析【转】


    Enum用法:

         1:常量

          在JDK1.5 之前,我们定义常量都是: public static fianl.... 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。

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

        2:switch

         JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。

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

       3:在enum中定义新方法

      public enum FieldType {
        DOUBLE  (JavaType.DOUBLE     , WIRETYPE_FIXED64         ),
        FLOAT   (JavaType.FLOAT      , WIRETYPE_FIXED32         ),
        INT64   (JavaType.LONG       , WIRETYPE_VARINT          ),
        UINT64  (JavaType.LONG       , WIRETYPE_VARINT          ),
        INT32   (JavaType.INT        , WIRETYPE_VARINT          ),
        FIXED64 (JavaType.LONG       , WIRETYPE_FIXED64         ),
        FIXED32 (JavaType.INT        , WIRETYPE_FIXED32         ),
        BOOL    (JavaType.BOOLEAN    , WIRETYPE_VARINT          ),
        STRING  (JavaType.STRING     , WIRETYPE_LENGTH_DELIMITED) {
          public boolean isPackable() { return false; }
        },
        GROUP   (JavaType.MESSAGE    , WIRETYPE_START_GROUP     ) {
          public boolean isPackable() { return false; }
        },
        MESSAGE (JavaType.MESSAGE    , WIRETYPE_LENGTH_DELIMITED) {
          public boolean isPackable() { return false; }
        },
        BYTES   (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
          public boolean isPackable() { return false; }
        },
        UINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
        ENUM    (JavaType.ENUM       , WIRETYPE_VARINT          ),
        SFIXED32(JavaType.INT        , WIRETYPE_FIXED32         ),
        SFIXED64(JavaType.LONG       , WIRETYPE_FIXED64         ),
        SINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
        SINT64  (JavaType.LONG       , WIRETYPE_VARINT          );
    
        FieldType(final JavaType javaType, final int wireType) {
          this.javaType = javaType;
          this.wireType = wireType;
        }
    
        private final JavaType javaType;
        private final int wireType;
    
        public JavaType getJavaType() { return javaType; }
        public int getWireType() { return wireType; }
    
        public boolean isPackable() { return true; }
      }

        4:复写方法

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

        5:实现接口

         所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。

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

        6:使用接口组织枚举

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

         

        7:关于枚举集合的使用

        java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档

        枚举和常量定义的区别

       一、 通常定义常量方法

              我们通常利用public final static方法定义的代码如下,分别用1表示红灯,3表示绿灯,2表示黄灯。

    public class Light {
            /* 红灯 */
            public final static int RED = 1;
    
            /* 绿灯 */
            public final static int GREEN = 3;
    
            /* 黄灯 */
            public final static int YELLOW = 2;
        }

        

      二、 枚举类型定义常量方法

          枚举类型的简单定义方法如下,我们似乎没办法定义每个枚举类型的值。比如我们定义红灯、绿灯和黄灯的代码可能如下:

    public enum Light {
            RED, GREEN, YELLOW;
        }

          我们只能够表示出红灯、绿灯和黄灯,但是具体的值我们没办法表示出来。别急,既然枚举类型提供了构造函数,我们可以通过构造函数和覆写toString方法来实现。首先给Light枚举类型增加构造方法,然后每个枚举类型的值通过构造函数传入对应的参数,同时覆写toString方法,在该方法中返回从构造函数中传入的参数,改造后的代码如下:

    public enum Light {
    
        // 利用构造函数传参
        RED(1), GREEN(3), YELLOW(2);
    
        // 定义私有变量
        private int nCode;
    
        // 构造函数,枚举类型只能为私有
        private Light(int _nCode) {
    
            this.nCode = _nCode;
    
        }
    
        @Override
        public String toString() {
    
            return String.valueOf(this.nCode);
    
        }
    
    }

        完整代码:

    public class LightTest {
    
        // 1.定义枚举类型
    
        public enum Light {
    
            // 利用构造函数传参
    
            RED(1), GREEN(3), YELLOW(2);
    
            // 定义私有变量
    
            private int nCode;
    
            // 构造函数,枚举类型只能为私有
    
            private Light(int _nCode) {
    
                this.nCode = _nCode;
    
            }
    
            @Override
            public String toString() {
    
                return String.valueOf(this.nCode);
    
            }
    
        }
    
        /**
         * 
         * @param args
         */
    
        public static void main(String[] args) {
    
            // 1.遍历枚举类型
    
            System.out.println("演示枚举类型的遍历 ......");
    
            testTraversalEnum();
    
            // 2.演示EnumMap对象的使用
    
            System.out.println("演示EnmuMap对象的使用和遍历.....");
    
            testEnumMap();
    
            // 3.演示EnmuSet的使用
    
            System.out.println("演示EnmuSet对象的使用和遍历.....");
    
            testEnumSet();
    
        }
    
        /**
         * 
         * 演示枚举类型的遍历
         */
    
        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);
    
            }
        }
    }

    执行结果如下:

    演示枚举类型的遍历 ......

    当前灯name:RED

    当前灯ordinal:0

    当前灯:1

    当前灯name:GREEN

    当前灯ordinal:1

    当前灯:3

    当前灯name:YELLOW

    当前灯ordinal:2

    当前灯:2

    演示EnmuMap对象的使用和遍历.....

    [key=RED,value=红灯]

    [key=GREEN,value=绿灯]

    [key=YELLOW,value=黄灯]

    演示EnmuSet对象的使用和遍历.....

    当前EnumSet中数据为:1

    当前EnumSet中数据为:3

    当前EnumSet中数据为:2

     

        下一个例子:

    public class EnumTest {
        
        public static void main(String args[]) {
            
            Color[]  cs = Color.values();
            for (Color c : cs)
            {
                System.out.println(c.ordinal());
                System.out.println(c.toString());
            }
        }
    
        enum Color {
            
            RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255);
            
            private Color(int redValue, int greenValue, int blueValue) 
            {
                this.redValue = redValue;
                this.greenValue = greenValue;
                this.blueValue = blueValue;
            }
            
            private int redValue;
            private int greenValue;
            private int blueValue;
        }
    }

    反编译工具得:

    // Referenced classes of package com.sunchao.demo:
    //            EnumTest
    
    static final class EnumTest$Color extends Enum
    {
    
        public static final EnumTest$Color RED;
        public static final EnumTest$Color GREEN;
        public static final EnumTest$Color BLUE;
        private int redValue;
        private int greenValue;
        private int blueValue;
        private static final EnumTest$Color ENUM$VALUES[];
    
        public static EnumTest$Color[] values()
        {
            EnumTest$Color aenumtest$color[];
            int i;
            EnumTest$Color aenumtest$color1[];
            System.arraycopy(aenumtest$color = ENUM$VALUES, 0, aenumtest$color1 = new EnumTest$Color[i = aenumtest$color.length], 0, i);
            return aenumtest$color1;
        }
    
        public static EnumTest$Color valueOf(String s)
        {
            return (EnumTest$Color)Enum.valueOf(com/sunchao/demo/EnumTest$Color, s);
        }
    
        static 
        {
            RED = new EnumTest$Color("RED", 0, 255, 0, 0);
            GREEN = new EnumTest$Color("GREEN", 1, 0, 255, 0);
            BLUE = new EnumTest$Color("BLUE", 2, 0, 0, 255);
            ENUM$VALUES = (new EnumTest$Color[] {
                RED, GREEN, BLUE
            });
        }
    
        private EnumTest$Color(String s, int i, int redValue, int greenValue, int blueValue)
        {
            super(s, i);
            this.redValue = redValue;
            this.greenValue = greenValue;
            this.blueValue = blueValue;
        }
    }

         显然,实际上enum声明定义的类型就是一个类。 而这些类都是类库中Enum类的子类(java.lang.Enum<E>)。它们继承了这个Enum中的许多有用的方法。我们对代码编译之后发现,编译器将enum类型单独编译成了一个字节码文件:Color.class。

        1、Color枚举类就是class,而且是一个不可以被继承的final类。其枚举值(RED,BLUE...)都是Color类型的类静态常量, 我们可以通过下面的方式来得到Color枚举类的一个实例:         

     Color c=Color.RED;

        注意:这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。 


       2、即然枚举类是class,当然在枚举类型中有构造器,方法和数据域。但是,枚举类的构造器有很大的不同: 
          (1) 构造器只是在构造枚举值的时候被调用。

          (2) 构造器只能私有private,绝对不允许有public构造器。 这样可以保证外部代码无法新构造枚举类的实例。这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。 但枚举类的方法和数据域可以允许外部访问。

          (3)枚举值在static静态代码块中初始化(类初始化),并维系一个数组(对应了values()方法),

      3、所有枚举类都继承了Enum的方法,下面我们详细介绍这些方法。 
           (1)  ordinal()方法: 返回枚举值在枚举类种的顺序。这个顺序根据枚举值声明的顺序而定。
                     Color.RED.ordinal();  //返回结果:0
                     Color.BLUE.ordinal();  //返回结果:1
           (2)  compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较象与指定对象的顺序。Enum中的compareTo返回的是两个枚举值的顺序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。(具体可见源代码)
                     Color.RED.compareTo(Color.BLUE);  //返回结果 -1
           (3)  values()方法: 静态方法,返回一个包含全部枚举值的数组。
                     Color[] colors=Color.values();
                     for(Color c:colors){
                            System.out.print(c+","); 
                     }//返回结果:RED,BLUE,BLACK YELLOW,GREEN,
           (4)  toString()方法: 返回枚举常量的名称。
                     Color c=Color.RED;
                     System.out.println(c);//返回结果: RED
           (5)  valueOf()方法: 这个方法和toString方法是相对应的,返回带指定名称的指定枚举类型的枚举常量。
                     Color.valueOf("BLUE");   //返回结果: Color.BLUE
           (6)  equals()方法: 比较两个枚举类对象的引用。

     参考:http://www.cnblogs.com/frankliiu-java/archive/2010/12/07/1898721.html

  • 相关阅读:
    HDU5446 Unknown Treasure
    C语言课设——通讯录操作系统
    判断设备是否横屏
    禁止用户横屏
    用javascript编写ps脚本
    用户鼠标指针的样式
    如何使用typescript开发node(自动编译,自动重启)
    CSS3:box-sizing:不再为匣子模型而烦恼
    命令行开启自动编译scss(webstrom可开启自动编译)
    TypeError: Cannot read property 'replace' of undefined ----angular2
  • 原文地址:https://www.cnblogs.com/onlysun/p/4574559.html
Copyright © 2020-2023  润新知