Java Enum类语法和用法解析

一.语法
  1. Enum的全称为enumeration,中文俗称枚举类,学过C/C++等语言的人,应该都对它略知一二. 但在Java语言规范中,是在JDK 5版本中才引入的,存放在 java.lang 包中。在Java版的Enum实质是语法糖,其声明方式如下:

1 package felix.fu
2 public enum Color{
3     RED,
4     BLUE,
5     BLACK,
6     YELLOW,
7     GREEN
8 } 

  enum是用来声明枚举的关键字,声明定义的类都隐含继承了一个父类(java.lang.Enum<E>),因此枚举不能再继承,但仍可实现接口。 该父类有两个私有属性name(枚举类型的名称)和ordinal(枚举实例被创建的序数),分别通过name()和ordinal()暴露出来了。定义在枚举类型里的每一个枚举实例都将映射到Enum的子类中,其实例的名称和在枚举类型里定义的顺序都会传入到这个构造函数里 protected Enum(String name, int ordinal)。

  2. 如果想更清楚了解一下Enum,可以用反编译工具把自己定义的枚举反编译一下就一目了然了,它就是一个普通的类, 只是Java语言规范从Code角度进行了限制,执行javap felix.fu.Color命令如下:

 1 public final class Color extends java.lang.Enum{
 2     public static final Color RED;
 3     public static final Color BLUE;
 4     public static final Color BLACK;
 5     public static final Color YELLOW;
 6     public static final Color GREEN;
 7     static {};
 8     public static Color[] values();
 9     public static Color valueOf(java.lang.String);
10 } 

  3. 如果定义的枚举有自己的构造函数必须声明私有的。

二.用法
  1.使用场景
  (1) 常用于对同一类常量进行分类
  (2) 声明接口方法时,输入参数类型采用枚举比用原始类型值常量更严谨.
  (3) 常量有时往往不仅仅只是一个值,有可能会包含多个属性,此时很适合用枚举
  (4) 有时常量对象需要从配置文件中读取其描述信息或者UI显示信息,此时也适合用枚举
  (5) 从Java语法层面来说,枚举可以在switch使用,在if中可直接进行比较
  (6) 声明枚举属性时最好用public final修饰,使用起来会非常方便
  (7) 自定义枚举时,建议不要使用自带的name()和ordinal()方法返回值来与原始值类型转换,这样业务不依赖其枚举的名字和顺序,如下:

 1 public enum Color {
 2     RED(0), BLUE(1), BLACK(2), YELLOW(3), GREEN(4);
 3     public final int value;
 4     /**
 5      * @param value
 6      */
 7     private Color(int value) {
 8         this.value = value;
 9     }
10     public static Color getInstance(int value) {
11         for (Color code : values()) {
12             if (code.value == value)
13                 return code;
14         }
15         return null;
16     }
17 } 

  2.实例:声明了一个基于枚举的简单异常框架,采用枚举来实现

 1 public interface ExceptionCode {
 2     /**
 3      * 返回异常码
 4      */
 5     String getErrorCode();
 6     /**
 7      * 返回异常描述
 8      * @param args 异常描述所用到的占位符值数组
 9      */
10     String getErrorCause(Object... args);
11 }
12 public enum DbExceptionCode implements ExceptionCode {
13     UNIQUE_KEY("10001", "主键约束错误"),
14     FOREIGN_KEY("10002", "外键约束错误");
15     public final String errorCode;
16     public final String errorName;
17     private DbExceptionCode(String errorCode, String errorName) {
18         this.errorCode = errorCode;
19         this.errorName = errorName;
20     }
21     @Override
22     public String getErrorCode() {
23         return errorCode;
24     }
25     @Override
26     public String getErrorCause(Object... args) {
27         // TODO need to read from configuration by errorCode
28         String errorCause = "";
29         return MessageFormat.format(errorCause, args);
30     }
31 }
32 public class DbException extends RuntimeException {
33     protected String errorCode;
34     protected String errorCause;
35     /**
36      * message format:BussinessErrorCode:BussinessErrorCause eg: 10010:无效Barcode[1000052]
37      *
38      * @param errorCode   error code of bussiness
39      * @param errorCause  error cause of bussiness
40      * @param cause
41      */
42     protected DbException(String errorCode, String errorCause, Throwable cause) {
43         super(errorCode + ":" + errorCause, cause);
44         this.errorCode = errorCode;
45         this.errorCause = errorCause;
46     }
47     public DbException(ExceptionCode exceptionCode, Object... args) {
48         this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(args));
49     }
50     public DbException(Throwable cause, ExceptionCode exceptionCode, Object... args) {
51         this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(args), cause);
52     }
53     public DbException(ExceptionCode exceptionCode, Throwable cause) {
54         this(exceptionCode.getErrorCode(), exceptionCode.getErrorCause(), cause);
55     }
56     protected DbException(String errorCode, String errorCause) {
57         this(errorCode, errorCause, null);
58     }
59     /**
60      * @return the errorCode
61      */
62     public String getErrorCode() {
63         return errorCode;
64     }
65     /**
66      * @return the errorCause
67      */
68     public String getErrorCause() {
69         return errorCause;
70     }
71 }

三. 弊端: 就是与原始值类似转换起来有点麻烦

四.通常定义常量方法和枚举定义常量方法区别
  以下内容可能有些无聊,但绝对值得一窥
  1.代码:

1 public class State {
2     public static final int ON = 1;
3     public static final Int OFF= 0;
4 } 

  首先,它不是类型安全的。你必须确保是int
  其次,你还要确保它的范围是0 和1
  最后,很多时候你打印出来的时候,你只看到1 和0 ,但其没有看到代码的人并不知道你的企图,抛弃你所有旧的public static final常量.

  2.可以创建一个enum 类,把它看做一个普通的类。除了它不能继承其他类了。(java 是单继承,它已经继承了Enum), 可以添加其他方法,覆盖它本身的方法

  3.switch() 参数可以使用enum 了  
  4.values() 方法是编译器插入到enum 定义中的static 方法,所以,当你将enum 实例向上转型为父类Enum 是,values() 就不可访问了。解决办法:在Class 中有一个getEnumConstants() 方法,所以即便Enum 接口中没有values() 方法,我们仍然可以通过Class 对象取得所有的enum 实例  
  5.无法从enum 继承子类,如果需要扩展enum 中的元素,在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组。达到将枚举元素进行分组。  
  6.使用EnumSet 代替标志。enum 要求其成员都是唯一的,但是enum 中不能删除添加元素。  
  7.EnumMap 的key 是enum ,value 是任何其他Object 对象。
  8.enum 允许程序员为eunm 实例编写方法。所以可以为每个enum 实例赋予各自不同的行为。
  9.使用enum 的职责链(Chain of Responsibility) . 这个关系到设计模式的职责链模式。以多种不同的方法来解决一个问题。然后将他们链接在一起。当一个请求到来时,遍历这个链,直到链中的某个解决方案能够处理该请求。
  10.使用enum 的状态机
  11.使用enum 多路分发

时间: 2024-12-21 21:20:39

Java Enum类语法和用法解析的相关文章

java File类的常见用法

File类简单用法! [java] view plain copy print? [java] view plain copy print? import java.io.File; import java.io.IOException; public class TestFile { public void createFile(String path){ File file=new File(path); if(!file.exists()){//判断文件是否存在 try { file.cr

Java中 for循环的用法解析

在Java程序中,要“逐一处理”――或者说,“遍历”――某一个数组或Collection中的元素的时候,一般会使用一个for循环来实现(当然,用其它种类的循环也不是不可以,只是不知道是因为for这个词的长度比较短,还是因为for这个词的含义和这种操作比较配,在这种时候for循环比其它循环常用得多).J2SE 1.5提供了另一种形式的for循环.借助这种形式的for循环,可以用更简单地方式来遍历数组和Collection等类型的对象.本文介绍使用这种循环的具体方式,说明如何自行定义能被这样遍历的类

Java中的底层魔法类Unsafe基本用法概述

1 引子 Java中没有指针,不能直接对内存地址的变量进行控制,但Java提供了一个特殊的类Unsafe工具类来间接实现.Unsafe主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资源.自主管理内存资源等,这些方法在提升Java运行效率.增强Java语言底层资源操作能力方面起到了很大的作用 .正如其名字unsafe,直接去使用这个工具类是不安全的,它能直接在硬件层(内存上)修改访问变量,而无视各种访问修饰符的限制.它几乎所有的公共方法API都是本地方法,这些方法是使用C/C++

java enum的用法

原始的常量定义: 1 public static fianl MON=“Mon”; 2 public static final TUE="Tue"; 语法(定义) 创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类).枚举类型符合通用模式Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称.枚举类型的每一个值都将映射到 protecte

Java enum的用法详解

在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. enum Signal { GREEN, YELLOW, RED } public cl

Java enum(枚举)的用法详解(转)

用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. enum Signal { GREEN, YELLOW, RED } pu

【转】Java enum的用法详解

用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. enum Signal { GREEN, YELLOW, RED } pu

最全面的Java多线程用法解析

最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); public Thread(Runnab

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