Java 5 新特性——枚举类型

一、概述

枚举(enum)类型是Java 5新增的特性,它是一种新的类型,允许用常量来表示特定的数据片断,而且全部都以类型安全的形式来表示。Tiger 专家、developerWorks 的多产作者 Brett McLaughlin 将解释枚举的定义,介绍如何在应用程序中运用枚举,以及它为什么能够让您抛弃所有旧的 public static final 代码。
枚 举在什么地方适用呢?一条普遍规则是,任何使用常量的地方,例如目前用 switch 代码切换常量的地方。如果只有单独一个值(例如,鞋的最大尺寸,或者笼子中能装猴子的最大数目),则还是把这个任务留给常量吧。但是,如果定义了一组值, 而这些值中的任何一个都可以用于特定的数据类型,那么将枚举用在这个地方最适合不过。
二、在枚举类型之前,Java是如何实现枚举功能的

在枚举类型出现之前,java是通过在接口或者类中定义public static final 的变量来实现的。比如,对于经典的红色警戒2中的英国狙击(sharp-shooter)手三个动作的描述:
/**
* 狙击手活动
*/
public interface SharpShooter_1 {
public static final int LOCKED = 1; //锁定
public static final int AIM = 2; //瞄准
public static final int SHOOT = 3; //射击
}
 
 
/**
* 测试方法
*/
public class TestDemo_1 {
public static void main(String args[]) {
TestDemo_1 test = new TestDemo_1();
test.doAction(1);
test.doAction(2);
test.doAction(3);
test.doAction(4);
}

/**
* 执行的动作
* @param action
*/
public void doAction(int action) {
switch (action) {
case SharpShooter_1.LOCKED:
System.out.println("1:锁定目标");
break;
case SharpShooter_1.AIM:
System.out.println("2:瞄准目标");
break;
case SharpShooter_1.SHOOT:
System.out.println("3:射击");
break;
default:
System.out.println("×:游戏还没有定义此动作!");
}
}
}
 
运行结果:
1:锁定目标
2:瞄准目标
3:射击
×:游戏还没有定义此动作!
[说明]:当然SharpShooter_1也可以声明为class,还可以直接将常量定义到TestDemo_1中,如果常量只是在类内部使用,就声明为private或者是protected,如果声明为public,则通常是与类功能相联系的常数。
[注 意]:switch语句的条件只能接收数值或字符(byte、short、int或char)或枚举(enum)类型的变量名或表达式。如 果没有符合条件数值或字符,则执行default语句,default语句不是必须的,如果没有默认要处理的动作,则default语句可省略。 break语句的作用是跳出循环块。

三、枚举类型的等价实现
Java代码 复制代码
  1. /**   
  2. * 狙击手活动(枚举类型实现)   
  3. */    
  4. public enum SharpShooter_2 {    
  5. LOCKED,    
  6. AIM,    
  7. SHOOT    
  8. }  
/** 
* 狙击手活动(枚举类型实现) 
*/ 
public enum SharpShooter_2 { 
LOCKED, 
AIM, 
SHOOT 
}
 
Java代码 复制代码
  1. /**   
  2. * 测试普通枚举类型   
  3. */    
  4. public class TestDemo_2 {    
  5.   
  6. public static void main(String args[]){    
  7. TestDemo_2 test=new TestDemo_2();    
  8. test.doAction(SharpShooter_2.LOCKED);    
  9. test.doAction(SharpShooter_2.AIM);    
  10. test.doAction(SharpShooter_2.SHOOT);    
  11. }    
  12. /**   
  13. * 执行的动作   
  14. * @param action   
  15. */    
  16. public void doAction(SharpShooter_2 action) {    
  17. switch (action) {    
  18. case LOCKED:    
  19. System.out.println("1:锁定目标");    
  20. break;    
  21. case AIM:    
  22. System.out.println("2:瞄准目标");    
  23. break;    
  24. case SHOOT:    
  25. System.out.println("3:射击");    
  26. break;    
  27. default:    
  28. System.out.println("×:游戏还没有定义此动作!");    
  29. }    
  30. }    
  31. }  
/** 
* 测试普通枚举类型 
*/ 
public class TestDemo_2 { 

public static void main(String args[]){ 
TestDemo_2 test=new TestDemo_2(); 
test.doAction(SharpShooter_2.LOCKED); 
test.doAction(SharpShooter_2.AIM); 
test.doAction(SharpShooter_2.SHOOT); 
} 
/** 
* 执行的动作 
* @param action 
*/ 
public void doAction(SharpShooter_2 action) { 
switch (action) { 
case LOCKED: 
System.out.println("1:锁定目标"); 
break; 
case AIM: 
System.out.println("2:瞄准目标"); 
break; 
case SHOOT: 
System.out.println("3:射击"); 
break; 
default: 
System.out.println("×:游戏还没有定义此动作!"); 
} 
} 
}
 
运行结果:
1:锁定目标
2:瞄准目标
3:射击
三、枚举类型的实质
在编译SharpShooter_2.java后,会生成一个SharpShooter_2.class文件,这说明枚举类型的实质还是一个类。因此,在某种程度上, enum关键字的作用就是class或者interface
当使用enum定义一个枚举类型时,实际上所定义的类型自动继承了java.lang.Enum类。而每个被枚举的成员实质就是一个枚举类型的实例, 他们默认都是public static final的。可以直接通过枚举类型名直接使用它们,枚举类型名,可以转为一个数值,或作字符匹配的方法来识别类型,所以我们在写枚举类型的时候,可以简单理解为一个个的串。
在 查询JDK1.5文档的java.lang.Enum类,里面清楚的说明:java.lang.Enum类是所有 Java 语言枚举类型的公共基本类。因此,所有枚举类型都拥有有java.lang.Enum类所提供的共有方法。因此,要学会使用枚举,还必须认识 java.lang.Enum类。下面将详细说明。
四、java.lang.Enum类
public abstract class Enum<E extends Enum<E>>extends Objectimplements Comparable<E>, Serializable这是所有 Java 语言枚举类型的公共基本类。
------------------
构造方法摘要
protected Enum(String name,int ordinal)
    单独的构造方法。程序员无法调用此构造方法。该构造方法用于由响应枚举类型声明的编译器发出的代码。
    参数:
    name - - 此枚举常量的名称,它是用来声明该常量的标识符。
    ordinal - - 枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
------------------
方法摘要
protected Object clone()
          抛出 CloneNotSupportedException。
int compareTo(E o)
          比较此枚举与指定对象的顺序。在该对象小于、等于或大于指定对象时,分别返回负整数、零或正整数。 枚举常量只能与相同枚举类型的其他枚举常量进行比较。该方法实现的自然顺序就是声明常量的顺序。
boolean equals(Object other)
          当指定对象等于此枚举常量时,返回 true。
Class<E> getDeclaringClass()
          返回与此枚举常量的枚举类型相对应的 Class 对象。当且仅当 e1.getDeclaringClass() == e2.getDeclaringClass() 时,两个枚举常量 e1 和 e2 的枚举类型才相同。(由该方法返回的值不同于由 Object.getClass() 方法返回的值,Object.getClass() 方法用于带有特定常量的类主体的枚举常量。)
int hashCode()
          返回枚举常量的哈希码。
String name()
          返回此枚举常量的名称,在其枚举声明中对其进行声明。 与此方法相比,大多数程序员应该优先考虑使用 toString() 方法,因为 toString 方法返回更加用户友好的名称。该方法主要设计用于特殊情形,其正确性取决于获得正确的名称,其名称不会随版本的改变而改变
int ordinal()
          返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 大多数程序员不会使用此方法。它被设计用于复杂的基于枚举的数据结构,比如 EnumSet 和 EnumMap。
String toString()
          返回枚举常量的名称,它包含在声明中。
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
          返回带指定名称的指定枚举类型的枚举常量。名称必须与在此类型中声明枚举常量所用的标识符完全匹配。(不允许使用额外的空白字符。)
   参数:
   enumType - 要从中返回常量的枚举类型的 Class 对象
   name - 要返回的常量名称
注意:ordinal() 方法得到枚举顺序的索引,默认从0开始。
五、枚举的高级用法
1、枚举方法
既然枚举的本质是类,那么定义枚举类型时也可以定义方法。比如:
Java代码 复制代码
  1. /**   
  2. * 带方法的枚举类型   
  3. */    
  4. public enum SharpShooter_3 {    
  5. LOCKED,    
  6. AIM,    
  7. SHOOT;    
  8.   
  9. public String getDesc() {    
  10. switch (this.ordinal()) {    
  11. case 0:    
  12. return "锁定目标";    
  13. case 1:    
  14. return "瞄准目标";    
  15. case 2:    
  16. return "射击";    
  17. default:    
  18. return "没有该枚举值!";    
  19. }    
  20. }    
  21. }   
  22.   
  23. /**   
  24. * 测试枚举方法   
  25. */    
  26. public class TestDemo_3 {    
  27. public static void main(String args[]) {    
  28. for (SharpShooter_3 enumSS : SharpShooter_3.values()) {    
  29. System.out.println(enumSS + " " + enumSS.getDesc());    
  30. }    
  31. }    
  32. }  
/** 
* 带方法的枚举类型 
*/ 
public enum SharpShooter_3 { 
LOCKED, 
AIM, 
SHOOT; 

public String getDesc() { 
switch (this.ordinal()) { 
case 0: 
return "锁定目标"; 
case 1: 
return "瞄准目标"; 
case 2: 
return "射击"; 
default: 
return "没有该枚举值!"; 
} 
} 
}

/** 
* 测试枚举方法 
*/ 
public class TestDemo_3 { 
public static void main(String args[]) { 
for (SharpShooter_3 enumSS : SharpShooter_3.values()) { 
System.out.println(enumSS + " " + enumSS.getDesc()); 
} 
} 
}
 
运行结果:
LOCKED 锁定目标
AIM 瞄准目标
SHOOT 射击

Process finished with exit code 0
  2、枚举构造方法
Java代码 复制代码
  1. /**   
  2. * 带私有构造方法的枚举类型   
  3. */    
  4. public enum SharpShooter_4 {    
  5. LOCKED("锁定目标"),    
  6. AIM("瞄准目标"),    
  7. SHOOT("射击");    
  8.   
  9. private String desc;        //枚举说明    
  10.   
  11. /**   
  12. * 私有的构造方法   
  13. */    
  14. private SharpShooter_4(String desc){    
  15. this.desc=desc;    
  16. }    
  17.   
  18. /**   
  19. * 获取枚举值的说明   
  20. * @return String   
  21. */    
  22. public String getDesc(){    
  23. return desc;    
  24. }    
  25. }   
  26.   
  27. /**   
  28. * 测试带私有构造方法的枚举类型   
  29. */    
  30. public class TestDemo_4 {    
  31. public static void main(String args[]) {    
  32. for (SharpShooter_4 enumSS : SharpShooter_4.values()) {    
  33. System.out.println(enumSS + " " + enumSS.getDesc());    
  34. }    
  35. }    
  36. }  
/** 
* 带私有构造方法的枚举类型 
*/ 
public enum SharpShooter_4 { 
LOCKED("锁定目标"), 
AIM("瞄准目标"), 
SHOOT("射击"); 

private String desc;        //枚举说明 

/** 
* 私有的构造方法 
*/ 
private SharpShooter_4(String desc){ 
this.desc=desc; 
} 

/** 
* 获取枚举值的说明 
* @return String 
*/ 
public String getDesc(){ 
return desc; 
} 
}

/** 
* 测试带私有构造方法的枚举类型 
*/ 
public class TestDemo_4 { 
public static void main(String args[]) { 
for (SharpShooter_4 enumSS : SharpShooter_4.values()) { 
System.out.println(enumSS + " " + enumSS.getDesc()); 
} 
} 
}
 
运行结果:
LOCKED 锁定目标
AIM 瞄准目标
SHOOT 射击

Process finished with exit code 0
3、实现接口的枚举
/**
* 说明接口
*/

public interface IDesc {
/**
* 获取说明信息
* @return String
*/

public String getDesc();
}
/**
* 实现了接口的枚举类型
*/

public enum SharpShooter_5 implements IDesc {
LOCKED( "锁定目标"),
AIM( "瞄准目标"),
SHOOT( "射击");

private String desc;         //枚举说明

/**
* 私有的构造方法
*/

private SharpShooter_5(String desc) {
this.desc = desc;
}

public String getDesc() {
return desc;
}
}
/**
* 测试实现了接口的枚举类型
*/

public class TestDemo_5 {
public static void main(String args[]) {
for (SharpShooter_5 enumSS : SharpShooter_5.values()) {
System.out.println(enumSS + " " + enumSS.getDesc());
}
}
}
运行结果:
LOCKED 锁定目标
AIM 瞄准目标
SHOOT 射击

Process finished with exit code 0

4、每个枚举值实现的自己的接口
/**
* 每个枚举值自己实现接口
*/

public enum SharpShooter_6 implements IDesc {
LOCKED(){
public String getDesc() {
return "锁定目标";
}
},

AIM{
public String getDesc() {
return "瞄准目标";
}
},

SHOOT{
public String getDesc() {
return "射击";
}
}
}
/**
* 测试每个枚举值自己实现接口
*/

public class TestDemo_6 {
public static void main(String args[]) {
for (SharpShooter_6 enumSS : SharpShooter_6.values()) {
System.out.println(enumSS + " " + enumSS.getDesc());
}
}
}
运行结果:
LOCKED 锁定目标
AIM 瞄准目标
SHOOT 射击

Process finished with exit code 0
5、带有抽象方法的枚举类型
/**
* 带有抽象方法的枚举类型
*/

public enum SharpShooter_7 {
LOCKED(){
public String getDesc() {
return "锁定目标";
}
},

AIM{
public String getDesc() {
return "瞄准目标";
}
},

SHOOT{
public String getDesc() {
return "射击";
}
};

/**
* 抽象方法,每个枚举值都必须自己实现
*
* @return String
*/

public abstract String getDesc();
}
/**
* 测试带有抽象方法的枚举类型
*/

public class TestDemo_7 {
public static void main(String args[]) {
for (SharpShooter_7 enumSS : SharpShooter_7.values()) {
System.out.println(enumSS + " " + enumSS.getDesc());
}
}
}
运行结果:
LOCKED 锁定目标
AIM 瞄准目标
SHOOT 射击

Process finished with exit code 0
六、对Java枚举类型的一些看法
枚 举的本质是类,在没有枚举之前,仍然可以按照java最基本的编程手段来解决需要用到枚举的地方。枚举屏蔽了枚举值的类型信息,不像在用 public static final定义变量必须指定类型。枚举是用来构建常量数据结构的模板,这个模板可扩展。枚举的使用增强了程序的健壮性,比如在引用一个不存在的枚举值的时 候,编译器会报错。枚举的更多用法还需要在开发中去研究创造,Java5、Java6增加了不少新的特性,技术在升级,对程序员来说就要学习。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值