枚举类型
关键词:枚举,方法,程序
枚举关键字允许您使用一组限定的命名值创建一个新类型,并将这些值视为常规程序组件。这对java的使用非常有帮助。
在初始化和清理结束时简要介绍了枚举。但是,现在您已经了解了Java中一些更深层次的问题,我们可以更详细地了解JavaSE5枚举特性。您将看到,使用枚举类型可以做一些非常有趣的事情,但本章还应该让您对其他方面有更多的了解。
您现在看到的语言特性,如泛型和反射。您还将学习更多的设计模式。
基本枚举特征
如Initializationamp;Cleanup中所示,可以通过调用枚举上的values()单步遍历枚举常量列表。values()方法按照枚举常数的声明顺序生成一个数组,所以您可以在foreach循环中使用生成的数组。
创建枚举时,编译器会为您生成一个关联的类。此类自动继承自java.lang.Enum,它提供了某些功能,您可以在本例中看到这些功能:
//: enumerated/EnumClass.java
import static net.mindview.util.Print.*;
enum Shrubbery { GROUND, CRAWLING, HANGING }
public class EnumClass {
public static void main(String[] args) {
for(Shrubbery s : Shrubbery.values()) {
print(s ' ordinal: ' s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) ' ');
printnb(s.equals(Shrubbery.CRAWLING) ' ');
print(s == Shrubbery.CRAWLING);
print(s.getDeclaringClass());
print(s.name()); print('----------------------'); }
// Produce an enum value from a string name:
for(String s : 'HANGING CRAWLING GROUND'.split(' ')) {
Shrubbery shrub = Enum.valueOf(Shrubbery.class, s); print(shrub); }}}
ordinal()方法生成一个int,指示每个枚举实例的声明顺序,从零开始。您始终可以使用==安全地比较枚举实例,并且会自动为您创建equals()和hashCode()。Enum类是可比较的,因此有一个compareTo()方法,它也是可序列化的。
如果在枚举实例上调用getDeclaringClass(),您将找到封闭的枚举类。
name()方法生成的名称与声明的名称完全相同,这也是使用toString()得到的结果。valueOf()是Enum的静态成员,并生成与传递给它的字符串名对应的Enum实例,如果不匹配,则引发异常。
静态导入枚举
从初始化和清理章节考虑BurrITO.java的变化:
//: enumerated/Spiciness.java
package enumerated;
public enum Spiciness {
NOT, MILD, MEDIUM, HOT, FLAMING}
//: enumerated/Burrito.java
package enumerated;
import static enumerated.Spiciness.*;
public class Burrito {
Spiciness degree;
public Burrito(Spiciness degree) { this.degree = degree;}
public String toString() { return 'Burrito is ' degree;}
public static void main(String[] args) {
System.out.println(new Burrito(NOT));
System.out.println(new Burrito(MEDIUM));
System.out.println(new Burrito(HOT)); } }
静态导入将所有枚举实例标识符带入本地名称空间,因此它们不需要限定。这是个好主意吗,还是限定所有枚举实例更好?这可能取决于代码的复杂性。编译器当然不会让您使用错误的类型,因此您唯一关心的是代码是否会让读者感到困惑。在许多情况下,这可能是好的,但你应该在个人的基础上进行评估。
请注意,如果枚举是在同一个文件或默认包中定义的,则不可能使用此技术(显然Sun内部有一些关于是否允许此操作的参数)。
添加枚举方法
除了不能从中继承之外,枚举可以像普通类一样处理。这意味着您可以向枚举添加方法。枚举甚至可以有一个main()。
您可能希望为枚举生成不同于默认toString()的描述,默认toString()只生成该枚举实例的名称,如您所见。为此,您可以提供一个构造函数来捕获额外信息,并提供其他方法来提供扩展描述,如下所示:
//: enumerated/OzWitch.java
// The witches in the land of Oz.
import static net.mindview.util.Print.*;
public enum OzWitch {
// Instances must be defined first, before methods:
WEST('Miss Gulch, aka the Wicked Witch of the West'),
NORTH('Glinda, the Good Witch of the North'),
EAST('Wicked Witch of the East, wearer of the Ruby '
'Slippers, crushed by Dorothyrsquo;s house'),
SOUTH('Good by inference, but missing');
private String description;
// Constructor must be package or private access:
private OzWitch(String description) {
this.description = description; }
public String getDescription() { return description; }
public static void main(String[] args) {
for(OzWitch witch : OzWitch.values())
print(witch ': ' witch.getDescription()); } }
请注意,如果要定义方法,则必须以分号结束枚举实例序列。此外,Java强制您将实例定义为枚举中的第一件事。如果试图在任何方法或字段之后定义它们,则会出现编译时错误。
构造函数和方法与常规类具有相同的形式,因为有一些限制,这是一个常规类。因此,您可以使用enum做几乎任何您想做的事情(尽管您通常会让它们非常普通)。
虽然构造函数在这里作为一个例子是私有的,但是使用什么访问并没有多大区别。构造函数只能用于创建枚举在枚举定义内声明的实例;一旦枚举定义完成,编译器将不允许您使用它创建任何新实例。
重写枚举方法
下面是为枚举生成不同字符串值的另一种方法。在本例中,实例名称是确定的,但我们希望重新格式化它们以供显示。覆盖枚举的toString()方法与覆盖常规类的toString()方法相同:
//: enumerated/SpaceShip.java
public enum SpaceShip {
SCOUT, CARGO, TRANSPORT, CRUISER, BATTLESHIP, MOTHERSHIP;
public String toString() {
String id = name();
String lower = id.substring(1).toLowerCase();
return id.charAt(0) lower; }
public static void main(String[] args) {
for(SpaceShip s : values()) {
System.out.println(s); } } }
toString()方法通过调用name()来获取宇宙飞船的名称,并修改结果,以便只将第一个字母大写。
switch语句中的枚举
枚举的一个非常方便的功能是在switch语句中使用它们的方式。通常,开关只能与整数值一起工作,但由于枚举具有已建立的整数顺序,并且可以使用ordinal()方法生成实例的顺序(显然编译器是这样做的),因此可以在开关语句中使用枚举。
虽然通常必须使用枚举实例的类型限定枚举实例,但不必在case语句中这样做。下面是一个使用枚举创建小状态的示例机器:
//: enumerated/TrafficLight.java
// Enums in switch statements.
import static net.mindview.util.Print.*;
// Define an enum type:
enum Signal { GREEN, YELLOW, RED, }
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch(color) {
// Note that you donrsquo;t have to say Signal.RED
// in the case statement:
case
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[595984],资料为PDF文档或Word文档,PDF文档可免费转换为Word
课题毕业论文、文献综述、任务书、外文翻译、程序设计、图纸设计等资料可联系客服协助查找。