`

【解惑】理解java枚举类型

阅读更多

枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字enum来定义一个枚举类。下面就是一个典型枚举类型的定义:

public enum Color{
    RED,BLUE,BLACK,YELLOW,GREEN
}

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

final enum hr.test.Color {
  
 // 所有的枚举值都是类静态常量
 public static final enum hr.test.Color RED;
 public static final enum hr.test.Color BLUE;
 public static final enum hr.test.Color BLACK;
 public static final enum hr.test.Color YELLOW;
 public static final enum hr.test.Color GREEN;
 
private static final synthetic hr.test.Color[] ENUM$VALUES;
  
  // 初始化过程,对枚举类的所有枚举值对象进行第一次初始化
 static {
       0  new hr.test.Color [1] 
      3  dup
      4  ldc <String "RED"> [16] //把枚举值字符串"RED"压入操作数栈
      6  iconst_0  // 把整型值0压入操作数栈
      7  invokespecial hr.test.Color(java.lang.String, int) [17] //调用Color类的私有构造器创建Color对象RED
     10  putstatic hr.test.Color.RED : hr.test.Color [21]  //将枚举对象赋给Color的静态常量RED。
      .........  枚举对象BLUE等与上同
    102  return
};
  
  // 私有构造器,外部不可能动态创建一个枚举类对象(也就是不可能动态创建一个枚举值)。
 private Color(java.lang.String arg0, int arg1){
     // 调用父类Enum的受保护构造器创建一个枚举对象
     3  invokespecial java.lang.Enum(java.lang.String, int) [38]
};
 
 public static hr.test.Color[] values();
  
   // 实现Enum类的抽象方法  
  public static hr.test.Color valueOf(java.lang.String arg0);
}
 

下面我们就详细介绍enum定义的枚举类的特征及其用法。(后面均用Color举例)

1、Color枚举类就是class,而且是一个不可以被继承的final类。其枚举值(RED,BLUE...)都是Color类型的类静态常量, 我们可以通过下面的方式来得到Color枚举类的一个实例:
                                                         Color c=Color.RED;
注意:这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。

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

enum Color{
                RED(255,0,0),BLUE(0,0,255),BLACK(0,0,0),YELLOW(255,255,0),GREEN(0,255,0);
                //构造枚举值,比如RED(255,0,0)
                private Color(int rv,int gv,int bv){
                 this.redValue=rv;
                 this.greenValue=gv;
                 this.blueValue=bv;
                }

                public String toString(){  //覆盖了父类Enum的toString()
                return super.toString()+"("+redValue+","+greenValue+","+blueValue+")";
                }
   
                private int redValue;  //自定义数据域,private为了封装。
                private int greenValue;
                private int blueValue;
 }

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

public static void main(String args[])
{
        // Color colors=new Color(100,200,300);  //wrong
           Color color=Color.RED;
           System.out.println(color);  // 调用了toString()方法
}   
 

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()方法: 比较两个枚举类对象的引用。

//JDK源代码:    
public final boolean equals(Object other) {
        return this==other;
}             


4、枚举类可以在switch语句中使用。

Color color=Color.RED;
switch(color){
        case RED: System.out.println("it's red");break;
        case BLUE: System.out.println("it's blue");break;
        case BLACK: System.out.println("it's blue");break;
}

 

分享到:
评论
18 楼 myloveiscomealone 2010-08-10  
非常感谢楼主的这篇文章,让我有一种茅塞盾开的感觉.以前枚举用得也不多,一直很迷糊!学习了!
17 楼 miaow 2010-08-04  
ihopethatwell 写道

完全没问题
public class BeanWithEnumAttribute {
	private Color color;
	public BeanWithEnumAttribute(Color color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "BeanWithEnumAttribute(" + color.getRedValue() + "," + color.getGreenValue() + "," + color.getBlueValue() + ")";
	}
	public static void main(String[] args) {
		BeanWithEnumAttribute bean = new BeanWithEnumAttribute(Color.BLUE);
		System.out.println(bean);
	}
}

输出
引用
BeanWithEnumAttribute(0,0,255)
16 楼 ihopethatwell 2010-08-04  
楼主,
如果我再 :   private int redValue;  //自定义数据域,private为了封装。  
                private int greenValue;  
                private int blueValue;  

添加以上三个属性的get方法,然后将其放到一个类中如:
public class MyEnumTest{
//此处添加进你的Enum Color ,当然要添加里面的三个属性get()

private Color color;
//其get和set方法省。。


public MyEnumTest() {}

public MyEnumTest(Color color ) {
this.color = color ;
}

public static void main(String[] args) {
//在此我想打印getRedValue()的值

//此处却是 空???
}
}

那么怎么处理?
15 楼 mercyblitz 2010-05-12  
利用多态更是暴力啊,呵呵。
本人写了个《Java面向对象设计最佳实践 - 枚举设计》
http://www.iteye.com/topic/664600,欢迎交流学习
14 楼 海盗大哥 2009-11-19  
讲解的相当棒~谢谢~
13 楼 duyouhua1214 2009-11-13  
一般吧,关于Enum的相关知识,在《java编程思想》这本书中有详细的介绍!
12 楼 qlhl2000 2009-09-29  
以前没有用过enum,看来挺好用,准备试试
11 楼 jltest 2009-09-28  
很棒的帖子。enum用得很少。这次子清楚多了
10 楼 goodfifa08 2009-09-28  
补充一点:
EnumMap<K extends Enum<K>,V>和EnumSet<E extends Enum<E>>两个集合类型,都是专门针对枚举类型。

EnumMap<Color, String> map = new EnumMap<Color, String>(Color.class);
		map.put(Color.RED, "red");
		map.put(Color.BLUE,"blue");
		
		for(Color c: Color.values()){
			System.out.println(map.get(c));
		}
9 楼 ZangXT 2009-09-28  
看一下Effective Java第一版,然后反编译一下enum类生成的代码,更能清楚的了解和应用。
实现分析:
http://blog.csdn.net/ZangXT/archive/2008/10/29/3174741.aspx
8 楼 putonyuer 2009-09-28  
wangdgsc 写道
枚举类可以用来做单例,很方便的



7 楼 徐风子 2009-09-28  
以前也经常用枚举,但一直没注意到原来是直接继承了java/lang/Enu类,刚才去看了一下字节码确实是这样,谢谢。
6 楼 yeminping 2009-09-27  
用的人是很少,但深入了解,在业务分析中恰当的应用应该了起到很好的作用
5 楼 wangdgsc 2009-09-27  
枚举类可以用来做单例,很方便的
4 楼 Heart.X.Raid 2009-09-27  
枚举类用的是不多,但是一旦需要用的时候却十分的方便。
3 楼 yanglei008 2009-09-27  
的确枚举类用的很少~~~
就算用到也没深入研究~~~
不错~~
2 楼 8vip 2009-09-27  
枚举我用的也很少 .
感谢楼主
1 楼 YiSingQ 2009-09-27  
以前对于Java的enum枚举类型没怎么注意,因为写代码相对少用了点,现在LZ你的文章写得详细,真的是学习了。。。

相关推荐

    java解惑java解惑java解惑

    java解惑java解惑java解惑java解惑java解惑java解惑

    Java解惑Java解惑

    Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑

    Java PUZZLE Java 解惑

    Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑

    Java解惑.pdf

    Java解惑.pdf Java解惑.pdf Java解惑.pdf Java解惑.pdf

    最新版的Java-解惑

    《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》

    JAVA 解惑 java经典

    JAVA解惑,你面包括一些java经典的问题。

    Java解惑 中文版

    Java解惑中文版 Java解惑 java健壮程序

    JAVA解惑(JAVA谜题) 中文版(PDF)

    Java解惑,是一本以大量java实例,讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java...

    Java解惑(中文版)_java_java解惑_solve65p_

    与java相关的的学习,适合初学者,可以看看

    JAVA解惑.pdf

    JAVA解惑.pdf JAVA解惑.pdf JAVA解惑.pdf

    java解惑 for all javaer

    讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java程序员阅读。

    java解惑(java谜题)中文版的

    java解惑(java谜题)中文版的. 值得一看的JAVA资料. Java puzzlers

    JAVA面试题解惑系列合集

    JAVA面试题解惑系列合集 JAVA面试题解惑系列合集 JAVA面试题解惑系列合集

    java解惑 书籍类 谜题

    java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑

    JAVA解惑 大量java实例 Java程序员阅读

    Java解惑,是一本以大量java实例,讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java...

    java解惑(+Java 解惑你知多少)

    任何具备Java知识的人都可以理解这些谜题,但甚至是最老练的程序员也会觉得它们具有挑战性。 多数的谜题都是些小程序,其行为诡秘,不可貌相。你能指出它们会做什么吗?根据这些谜题用到的特性以及各题的详细解惑方案...

    Java解惑/Java谜题(CHM)

    我整理出来的Java解惑/谜题的CHM版本,包括目录、全文搜索和收藏夹。比目前Word/PDF版本的多个目录,比TXT版本的多一些格式。-- 如果不能打开CHM,请按下面方法解决:-- 右键点击chm文档,查看属性,可以看到...

    <好书>java解惑(java puzzlers),过来挑战吧

    &lt;好书&gt;java解惑(java puzzlers),过来挑战吧

    Java解惑 java

    Java解惑 Java解惑 Java解惑

Global site tag (gtag.js) - Google Analytics