Java枚举类型_第1页
Java枚举类型_第2页
Java枚举类型_第3页
Java枚举类型_第4页
Java枚举类型_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Java 枚举类型入门这里就将为大家谈谈 Java 枚举类型,static final 通常跟的是一个 int 类型的常数,所以有时候可以用 int 型代替枚举。在 Java 中,枚举确实是一个类。Tiger 中的一个重要新特性是枚举构造,它是一种新的 Java 枚举类型,允许用常量来表示特定的数据片断,而且全部都以类型安全的形式来表示。Tiger 专家、developerWorks 的多产作者 Brett McLaughlin 将解释枚举的定义,介绍如何在应用程序中运用枚举,以及它为什么能够让您抛弃所有旧的 public static final 代码。您已经知道,Java 代码的两个基本的

2、构造块是类 和接口。现在 Tiger 又引入了枚举,一般简称它为 enum。这个新类型允许您表示特定的数据点,这些数据点只接受分配时预先定义的值集合。 当然,熟练的程序员可以用静态常量实现这项功能,如清单 1 所示:清单 1. public static final 的常量1. public class OldGrade 2.3. public static final int A = 1;4. public static final int B = 2;5. public static final int C = 3;6. public static final int D = 4;7. p

3、ublic static final int F = 5;8. public static final int INCOMPLETE = 6;9. 说明:我要感谢 OReilly 媒体公司,该公司允许在本文中使用我撰写的 Java 1.5 Tiger:A Developers Notebook 一书中“枚举”这一章中的代码示例(请参阅参考资料)。然后您就可以让类接受像 OldGrade.B 这样的常量,但是在这样做的时候,请记住这类常量是 Java 中 int 类型的常量,这意味着该方法可以接受任何 int 类型的值,即使它和OldGrade 中定的所有级别都不对应。因此,您需要检测上界和下界

4、,在出现无效值的时候,可能还要包含一个 IllegalArgumentException。而且,如果后来又添加另外一个级别(例如OldGrade.WITHDREW_PASSING),那么必须改变所有代码中的上界,才能接受这个新值。换句话说,在使用这类带有整型常量的类时,该解决方案也许可行,但并不是非常有效。幸运的是,枚举提供了更好的方法。定义枚举清单 2 使用了一个可以提供与清单 1 相似的功能的枚举:清单 2. 简单的枚举类型10. package com.oreilly.tiger.ch03;11.12. public enum Grade 13. A, B, C, D, F, INCOM

5、PLETE14. ;在这里,我使用了新的关键字 enum,为 enum 提供了一个名称,并指定了允许的值。然后,Grade 就变成了一个枚举类型,您可以按清单 3 所示的方法使用它:清单 3. 使用枚举类型15. package com.oreilly.tiger.ch03;16.17. public class Student 18.19. private String firstName;20. private String lastName;21. private Grade grade;22.23. public Student(String firstName, String las

6、tName) 24. this.firstName = firstName;25. this.lastName = lastName;26. 27.28. public void setFirstName(String firstName) 29. this.firstName = firstName;30. 31.32. public String getFirstName() 33. return firstName;34. 35.36. public void setLastName(String lastName) 37. this.lastName = lastName;38. 39

7、.40. public String getLastName() 41. return lastName;42. 43.44. public String getFullName() 45. return new StringBuffer(firstName)46. .append( )47. .append(lastName)48. .toString();49. 50.51. public void assignGrade(Grade grade) 52. this.grade = grade;53. 54.55. public Grade getGrade() 56. return gr

8、ade;57. 58. 用以前定义过的类型建立一个新的枚举(grade)之后,您就可以像使用其他成员变量一样使用它了。当然,枚举只能分配枚举值中的一个(例如,A、C 或 INCOMPLETE)。而且,在 assignGrade() 中是没有进行错误检测的代码,也没有考虑边界情况,请注意这是如何做到。使用 Java 枚举值迄今为止,您所看到的示例都相当简单,但是枚举类型提供的东西远不止这些。您可以逐个遍历枚举值,也可以在 switch 语句中使用枚举值,枚举是非常有价值的。遍历 Java 枚举值下面我们用一个示例显示如何遍历枚举类型的值。清单 4 所示的这项技术,适用于调试、快速打印任务以及把枚

9、举加载到集合(我很快将谈到)中的工具:清单 4. 遍历枚举值59. public void listGradeValues(PrintStream out) throws IOException 60. for (Grade g : Grade.values() 61. out.println(Allowed value: + g + );62. 63. 运行这段代码,将得到清单 5 所示的输出:清单 5. 迭代操作的输出64. Allowed Value: A65. Allowed Value: B66. Allowed Value: C67. Allowed Value: D68. All

10、owed Value: F69. Allowed Value: INCOMPLETE这里有许多东西。首先,我使用了 Tiger 的新的 for/in 循环(也叫作 foreach 或 增强的 for)。另外,您可以看到 values() 方法返回了一个由独立的 Grade 实例构成的数组,每个数组都有一个枚举类型的值。换句话说,values() 的返回值是 Grade。在枚举间切换能够在枚举的值之间移动很好,但是更重要的是根据枚举的值进行决策。您当然可以写一堆 if (grade.equals(Grade.A) 类型的语句,但那是在浪费时间。Tiger 能够很方便地把枚举支持添加到过去的好东西

11、 switch 语句上,所以它很容易使用,而且适合您已知的内容。清单 6 向将展示如何解决这个难题:清单 6. 在枚举之间切换70. public void testSwitchStatement(PrintStream out) throws IOException 71. StringBuffer outputText = new StringBuffer(student1.getFullName();72.73. switch (student1.getGrade() 74. case A:75. outputText.append( excelled with a grade of A

12、);76. break;77. case B: / fall through to C78. case C:79. outputText.append( passed with a grade of )80. .append(student1.getGrade().toString();81. break;82. case D: / fall through to F83. case F:84. outputText.append( failed with a grade of )85. .append(student1.getGrade().toString();86. break;87.

13、case INCOMPLETE:88. outputText.append( did not complete the class.);89. break;90. 91.92. out.println(outputText.toString();93. 在这里,枚举值被传递到 switch 语句中(请记住,getGrade() 是作为 Grade 的实例返回的),而每个 case 子句将处理一个特定的值。该值在提供时没有枚举前缀,这意味着不用将代码写成 case Grade.A,只需将其写成 case A 即可。如果您不这么做,编译器不会接受有前缀的值。现在,您应该已经了解使用 switch

14、语句时的基本语法,但是还有一些事情您需要知道。在使用 switch 之前进行计划正如您所期待的,在使用枚举和 switch 时,您可以使用 default 语句。清单 7 显示了这个用法:清单 7. 添加一个 default 块94. public void testSwitchStatement(PrintStream out) throws IOException 95. StringBuffer outputText = new StringBuffer(student1.getFullName();96.97. switch (student1.getGrade() 98. case

15、A:99. outputText.append( excelled with a grade of A);100. break;101. case B: / fall through to C102. case C:103. outputText.append( passed with a grade of )104. .append(student1.getGrade().toString();105. break;106. case D: / fall through to F107. case F:108. outputText.append( failed with a grade o

16、f )109. .append(student1.getGrade().toString();110. break;111. case INCOMPLETE:112. outputText.append( did not complete the class.);113. break;114. default:115. outputText.append( has a grade of )116. .append(student1.getGrade().toString();117. break;118. 119.120. out.println(outputText.toString();1

17、21. 研究以上代码可以看出,任何没有被 case 语句处理的枚举值都会被 default 语句处理。这项技术您应当坚持采用。原因是:假设 Grade 枚举被您的小组中其他程序员修改(而且他忘记告诉您这件事)成清单 8 所示的版本:清单 8. 给 Grade 枚举添加一个值122. package com.oreilly.tiger.ch03;123.124. public enum Grade 125. A, B, C, D, F, INCOMPLETE,126. WITHDREW_PASSING, WITHDREW_FAILING127. ;现在,如果使用清单 6 的代码所示的新版 Gra

18、de,那么这两个新值会被忽略。更糟的是,您甚至看不到错误!在这种情况下,存在某种能够通用的 default 语句是非常重要的。清单7 无法很好地处理这些值,但是它会提示您还有其他值,您需要处理这些值。一旦完成处理,您就会有一个继续运行的应用程序,而且它不会忽略这些值,甚至还会指导您下一步的动作。所以这是一个良好的编码习惯。枚举和集合您所熟悉的使用 public static final 方法进行编码的那些东西,可能已经转而采用枚举的值作为映射的键。如果您不知道其中的含义,请参见清单 9,它是一个公共错误信息的示例,在使用 Ant 的 build 文件时,可能会弹出这样的消息,如下所示:清单 9

19、. Ant 状态码128. package com.oreilly.tiger.ch03;129.130. public enum AntStatus 131. INITIALIZING,132. COMPILING,133. COPYING,134. JARRING,135. ZIPPING,136. DONE,137. ERROR138. 为每个状态码分配一些人们能读懂的错误信息,从而允许人们在 Ant 提供某个代码时查找合适的错误信息,将这些信息显示在控制台上。这是映射(Map)的一个绝好用例,在这里,每个映射(Map)的键都是一个枚举值,而每个值都是键的错误信息。清单 10 演示了该映

20、射的工作方式:清单 10. 枚举的映射(Map)139. public void testEnumMap(PrintStream out) throws IOException 140. / Create a map with the key and a String message141. EnumMap antMessages =142. new EnumMap(AntStatus.class);143.144. / Initialize the map145. antMessages.put(AntStatus.INITIALIZING, Initializing Ant.);146.

21、antMessages.put(AntStatus.COMPILING, Compiling Java classes.);147. antMessages.put(AntStatus.COPYING, Copying files.);148. antMessages.put(AntStatus.JARRING, JARring up files.);149. antMessages.put(AntStatus.ZIPPING, ZIPping up files.);150. antMessages.put(AntStatus.DONE, Build complete.);151. antMe

22、ssages.put(AntStatus.ERROR, Error occurred.);152.153. / Iterate and print messages154. for (AntStatus status : AntStatus.values() ) 155. out.println(For status + status + , message is: +156. antMessages.get(status);157. 158. 该代码使用了泛型(generics)(请参阅参考资料)和新的 EnumMap 构造来建立新映射。而且,枚举值是通过其 Class 对象提供的,同时提供

23、的还有映射值的类型(在该例中,它只是一个简单的字符串)。该方法的输出如清单 11 所示:Java 枚举类型中的 Class 对象您可能已经注意到,清单 10 中的示例代码实际上表明 Tiger 把枚举当作类,这可以从 AntStatus 的 Class 对象那里得到证明,该对象不仅可用,而且正被实际使用。这是真的。归根到底, Tiger 还是把枚举看成是特殊的类类型。有关枚举的具体实现细节,请参阅 Java 5.0 Tiger: A Developers Notebook 的第三章(请参阅参考资料)。清单 11. 清单 10 的输出159. echo Running AntStatusTester.160. java For status INITIALIZING, message is: Initializing Ant.1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论