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

时间: 2024-10-17 00:38:29

Java Enum解析【转】的相关文章

Rhythmk 一步一步学 JAVA (20) JAVA enum常用方法

JAVA 枚举定义常用方法: 1.static Enum valueOf(Class enum,String name) 返回指定name的枚举类型 2.Static Enum values[] 返回枚举常量集合 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

JAVA - Sql解析工具fdb-sql-parser简单使用

由于想要解决Mybatis分页插件中count查询效率问题,因为order by很影响效率,所以需要一种方式处理sql,将order by 语句去掉. 试了好几个sql解析工具,最后选择了fdb-sql-parser. Maven依赖: <dependency> <groupId>com.foundationdb</groupId> <artifactId>fdb-sql-parser</artifactId> <version>1.

java enum

小谈Java Enum的多态性 博客分类: Java JavaAppleJDKJVMIDEA Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态?不过还是先看看"现象"吧: Java代码   public enum Fruit { APPLE, PEAR, PEACH, ORANGE; } 以上是一个简单的enum,关于它,我要补充一点: Fruit是java.lang.Enum的子类,准确地说,是Enum<Fruit>

java dom4j解析xml实例(2)

java利用dom4j解析xml 需要的jar包: dom4j官方网站在 http://www.dom4j.org/ 下载dom4j-1.6.1.zip 解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要加入包jaxen-1.1-beta-7.jar(如果不导入这个架包程序可以执行出结果,但最后会报异常) 将相关jar包引入后,实际解析操作如下:  1.要解析的xml文件province.xml: <china dn="d

org.w3c.dom(java dom)解析XML文档

位于org.w3c.dom操作XML会比较简单,就是将XML看做是一颗树,DOM就是对这颗树的一个数据结构的描述,但对大型XML文件效果可能会不理想 首先来了解点Java DOM 的 API:1.解析器工厂类:DocumentBuilderFactory 创建的方法:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 2.解析器:DocumentBuilder 创建方法:通过解析器工厂类来获得 DocumentBu

java XML解析

package com.kpsh.myself; import java.io.File;import java.io.FileInputStream;import java.util.List; import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory; import org.dom4j.Document;import org.dom4j.DocumentHelper;imp

JAVA SAX解析XML文件

[代码] [Java]代码view sourceprint?001package SAXparse;002 003 004import java.io.FileInputStream;005import java.lang.reflect.Array;006import java.lang.reflect.InvocationTargetException;007import java.lang.reflect.Method;008import java.text.ParseException;

Java XML解析技术

XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便.XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已.基本的解析方式有两种,一种叫SAX,另一种叫DOM. DOM的全称是Document Object Model,也即文档对象模型.在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作.通过DOM接口,应用程

Java enum枚举是怎么回事

Java1.5之前是没有枚举的,如果想使用类似枚举的特性,也即是需要使用常量的时候,可以通过如下代码完成: Java中的常量定义: publicclassSex2 { publicstaticfinalintGIRL = 1; publicstaticfinalintBOY = 2; publicstaticvoid main(String[]args) { System.out.println(Sex2.GIRL); } } 但是这样做有个缺点,就是不够直观,我们打印出Sex2.GIRL,看到