- 浏览: 3801 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
文章分类
最新评论
-
xiangxuehai_jiaer:
以前都没太用过枚举类,甚至不知道!感谢作者!
枚举类型 -
tworthree:
这个在线编辑器让我感觉还停留在web1.0时代
枚举类型
枚举类型
最近看Java in Nutshell 5th,发觉从来未用过的枚举很有意思,于是翻译如下,如果大家反映平平,那我就不再制造这么多网络垃圾了。(非严格翻译,望指正错误,以免误导群众。鼓励参看英文版,)
4.2. 枚举类型:
在前面的章节中,我们已经学习了用class关键字来定义类,用Interface关键字来定义接口,这部分介绍enum关键字来定义一个枚举类型(也称枚举)。枚举类型是Java5.0新特征,所以不能在之前Java版本中用。
我们从基本的开始:怎样定义和使用一个枚举类型:涉及到枚举类型名称和值。下一步,我们讨论枚举的高级特性,同时介绍一下在5.0之前的版本怎样模拟枚举。
4.2.1.枚举基础
一个枚举通常是定义一个很小的有具体值的集合引用,这些值在定义中一一罗列出来。这是Java中枚举类型的简单例子:
public enum DownloadStatus { CONNECTINS, READING, DONE, ERROR }
像class和interface一样,enum关键字定义了一个新引用类型。上面这行Java代码定义了一个名字是DownloadStatus的枚举类型。这个类型的主体仅仅有被逗号隔开的枚举值表,这些值有点像static final域,所以我们将它们大写,引用它们时要用到枚举名称,像这样:DownloadStatus.CONNECTING, DownloadStatus.READING……DownloadStatu类型的变量只可以是这四个值中其一或者null,不能为其他的值。这个枚举类型的值叫做枚举值(enumerated values)或者枚举常量(enum constants)。
枚举类型的定义可能比这复杂,复杂用法我们稍后将介绍。但是到现在为止,你可以使用上述语法定义简单但是非常有用的枚举了!
4.2.1.1 枚举类型是类(classes)
在Java5.0之前的版本,我们可能在类或接口中使用整型常量来定义DownloadStatus中的值:
public static final int CONNECTING = 1;
public static final int READING = 2;
public static final int DONE = 3;
public static final int ERROR = 4;
这种整型常量的用法有许多缺点,最重要的缺点是它非类型安全。如果一个方法期望接受一个DownloadStatus的常量值,但我们传一个UploadStatus的常量值,也不会发生错误!编译器不能分辨我在使用UploadStatus.DONE时本应该使用DownloadStatus.DONE。很幸运的是,枚举类型不只是简单的整型常量,这种用enum关键字定义的类型实际上是一个类,它的枚举值就是这个类的实例!这点能提供类型安全检查:如果一个方法期望UploadStatus的枚举值,而我传了一个DownloadStatus的枚举值,编译器就会报错。但是,枚举类并没有公共构造器,所以不能实例化一个没有被定义的枚举值。如果一个方法期望一个DownloadStatus枚举值,我们就不能传递一个没有在这个枚举中定义的值。
4.2.1.2 枚举类型的特征
你想知道枚举并高效地使用枚举,务必要知道下表所描述的枚举类型的基本特征。
• 枚举类型没有公共构造器,唯一定义实例的方法就是在枚举中声明他们。
• 枚举值没有实现克隆接口(Cloneable),因此不能克隆一个已经存在的枚举值。.
• 枚举值实现了java.io.Serializable接口,因此它能被序列化,但Java序列机制使用了特别的方法以保证不会有新的枚举值被创建。
• 枚举值是不可变的:每个枚举值保持它的性质。
• 枚举类型的实例在其类中是按public static final域存储的,因为这些值是final的,它们不能被覆写:你不能这样做: DownloadStatus.DONE= DownloadStatus.ERROR
• 习惯上,枚举值像其他static final域一样,都是大写。
• 因为对枚举值有一系列限制,所以我们可以用 = = 来比较枚举值,而不需要equals方法
• 但是枚举类型确实有equals方法,这个内部实质是使用 = = 并且是final的,所以不能被覆写,当枚举值作为集合(比如Set,List,Map)元素时,这个equals方法能用到。
• 枚举类型有一个hashCode()方法,它也是final的,当枚举值作为HashMap元素时,这个hashCode方法能用到。
• 枚举类型实现了Comparable接口,并且compareTo方法实现是基于枚举值声明时的顺序。
• 枚举类型有toString方法,返回枚举值的名称,比如DownloadStatus.DONE.toString()默认返回字符串“DONE”,这个方法不是final的,我们可以提供一个自定义的实现。
• 枚举类型提供一个静态valueOf方法,功能toString()恰恰相反。比如说DownloadStatus.valueOf(“DONE”)返回DownloadStatus.DONE。
• 枚举类型提供一个final的ordinal方法,返回一个枚举值的整数值,这个值取决于它在枚举中声明的顺序,通常我们并不需要使用该方法,but it is used by a number of enum-related facilities, as described later in the chapter.
• 每个枚举的类型定义了一个静态方法values(),它返回一个包含所有枚举值的数组,顺序是基于枚举值声明的顺序,在迭代所有枚举值的时候很有用。
• 枚举类型是java.lang.Enum的子类,是Java5.0中的新特征(Enum本身不是一个枚举类型)。我们不能显式继承Enum来产生一个枚举类型,否则会产生编译错误,唯一定义枚举类型的方法是使用enum关键字。
• 枚举类型不能被继承,枚举类型是final的,但是定义枚举类型时并不需要也不允许final关键字,同时也不能使用abstract(后面章节我们会指出这点)。
• 像类一样,枚举类型可以实现接口,后面我们在枚举中定义方法时会看到。
4.2.2.使用枚举类型
接下来的部分描述了枚举类型的普通用法,我们来看看枚举值在switch语句中是怎么用的,最后介绍两个很重要的新集合EnumSet和EnumMap
4.2.2.1 枚举和switch语句
在Java1.4或之前的版本,switch语句只支持int、short、char和byte值。但是switch语句在Java5.0增加了对枚举类型的支持,枚举类型是一个有限集合,它们也理想地适用于switch语句。这个用法中所有的case标签必须是枚举类型的实例,即枚举值。如下显示:
DownloadStatus status = imageLoader.getStatus();
switch(status) {
case CONNECTING:
imageLoader.waitForConnection();
imageLoader.startReading();
break;
case READING:
break;
case DONE:
return imageLoader.getImage();
case ERROR:
throw new IOException(imageLoader.getError());
}
注意case标签仅仅是常量名称:switch用法不允许类名DownloadStatus在这出现,这种用法也非常方便。但是在其他的情况下(除了import static之外),我们需要使用枚举类型的名称。如果上例status为空,就会抛出空指针异常,case不允许使用null作为标签值。如果在switch语句中使用枚举类型时即没有default标签,又没有处理所有的枚举值,那么编译器就会提出-Xlint警告,你需要处理所有的枚举值。但是,如果在运行期间这个枚举类型又出现了新的枚举值,我们就需要在处理所有的枚举情况之后,再加上default标签检查这种意外发生,示例如下:
default: throw new AssertionError("Unexpected enumerated value: " + status);
4.2.2.2 EnumMap
一种普通的编程习惯:使用整型常量而不是枚举值作为数组的索引,比如说DownloadStatus值作为0-3的整数常量来定义,我们可以这样编码:
String[] statusLineMessages = new String[] {
"Connecting...", // CONNECTING
"Loading...", // READING
"Done.", // DONE
"Download Failed." // ERROR
};
int status = getStatus();
String message = statusLineMessages[status];
上例中,这种技术创建了枚举的整型常量到字符串的映射,我们不能用枚举值作为数组的索引,但能用来作为java.util.Map的健值。Java5.0中定义了一个新的java.util.EnumMap类,所以很容易实现这种用法。EnumMap健值要求是有限的枚举,它的values是容纳在一个数组中的。这种实现意味着它要比HashMap更加高效,上例用EnumMap实现是这样的:
EnumMap<DownloadStatus,String> messages =
new EnumMap<DownloadStatus,String>(DownloadStatus.class);
messages.put(DownloadStatus.CONNECTING, "Connecting...");
messages.put(DownloadStatus.READING, "Loading...");
messages.put(DownloadStatus.DONE, "Done.");
messages.put(DownloadStatus.ERROR, "Download Failed.");
DownloadStatus status = getStatus();
String message = messages.get(status);
像Java5.0其他集合一样,EnumMap是支持泛型参数的。
某些时候使用EnumMap来关联枚举值和value是很恰当的。你也可以在枚举类型定义中创建这种必要的关联,这种实现稍后的章节我们再来学习。
4.2.2.3 EnumSet
另一种普遍的编程习惯:使用整型常量而不是枚举值来定义所有的2的幂,以便这些幂能很方便地用位标记(bit-flags)来表示。考虑下面这些标记,我们将它们应用在了一种美国浓咖啡饮料上。
public static final int SHORT = 0x01; // 8 ounces
public static final int TALL = 0x02; // 12 ounces
public static final int GRANDE = 0x04; // 16 ounces
public static final int DOUBLE = 0x08; // 2 shots of espresso
public static final int SKINNY = 0x10; // made with nonfat milk
public static final int WITH_ROOM = 0x20; // leave room for cream
public static final int SPLIT_SHOT = 0x40; // half decaffeinated
public static final int DECAF = 0x80; // fully decaffeinated
这些2的幂常量能进行位或操作得到另外一个常量:
int drinkflags = DOUBLE | SHORT | WITH_ROOM;
按位与操作能检验各个位是否为0:
boolean isBig = (drinkflags & (TALL | GRANDE)) != 0;
我们可以看出这些这些整型标记组成了一个特殊的集合。因为这种处理枚举值的方法重要并且常用,所以Java 5.0 提供有特殊目的java.util.EnumSet类。像EnumMap一样,EnumSet对枚举类型非常有效。它要求元素必须是一
个枚举类型。
上例的浓咖啡代码用一个枚举和EnumSet可以覆写成如下:
public enum DrinkFlags {
SHORT, TALL, GRANDE, DOUBLE, SKINNY, WITH_ROOM, SPLIT_SHOT, DECAF
}
EnumSet<DrinkFlags> drinkflags =
EnumSet.of(DrinkFlags.DOUBLE, DrinkFlags.SHORT, DrinkFlags.WITH_ROOM);
boolean isbig =
drinkflags.contains(DrinkFlags.TALL) ||
drinkflags.contains(DrinkFlags.GRANDE);
注意:应用简单的static import 我们可以将代码简化得更紧凑
// Import all static DrinkFlag enum constants
import static com.davidflanagan.coffee.DrinkFlags.*;
EnumSet类定义了一系列有用的工厂方法来初始化枚举值,上面的of()方法被覆写,参数使用变长参数。下面你将看到of()的用法。
// Make the following examples fit on the page better
import static com.davidflanagan.coffee.DrinkFlags.*;
// We can remove individual members or sets of members from a set.
// Start with a set that includes all enumerated values, then remove a subset:
EnumSet<DrinkFlags> fullCaffeine = EnumSet.allOf(DrinkFlags.class);
fullCaffeine.removeAll(EnumSet.of(DECAF, SPLIT_SHOT));
// Here's another technique to achieve the same result:
EnumSet<DrinkFlags> fullCaffeine =
EnumSet.complementOf(EnumSet.of(DECAF,SPLIT_SHOT));
// Here's an empty set if you ever need one
// Note that since we don't specify a value, we must specify the element type
EnumSet<DrinkFlags> plainDrink = EnumSet.noneOf(DrinkFlags.class);
// You can also easily describe a contiguous subset of values:
EnumSet<DrinkFlags> drinkSizes = EnumSet.range(SHORT, GRANDE);
// EnumSet is Iterable, and its iterator returns values in ordinal() order,
// so it is easy to loop through the elements of an EnumSet.
for(DrinkFlag size : drinkSizes) System.out.println(size);
这个例子展示了EnumSet的用法和更多潜力,但是要注意的是:EnumSet<DrinkFlags> 用来描述这个浓咖啡并不合适。它可能如例所示被重新定义或者根本就不包含任何值。最根本的问题在于这些枚举值只是上例标记的简单转换,更好并且更复杂的实现是用下例的接口。各个相关属性组成一个枚举类型,而Flags需要其他五个枚举类型的至多一个值。这些枚举类型嵌套在这个接口中,这个例子吸取了枚举类型安全的优点,getSize方法不能返回一个Drink枚举值。
public interface Espresso {
enum Drink { LATTE, MOCHA, AMERICANO, CAPPUCCINO, ESPRESSO }
enum Size { SHORT, TALL, GRANDE }
enum Strength { SINGLE, DOUBLE, TRIPLE, QUAD }
enum Milk { SKINNY, ONE_PERCENT, TWO_PERCENT, WHOLE, SOY }
enum Caffeine { REGULAR, SPLIT_SHOT, DECAF }
enum Flags { WITH_ROOM, EXTRA_HOT, DRY }
Drink getDrink();
Size getSize();
Strength getStrength();
Milk getMilk();
Caffeine getCaffeine();
java.util.Set<Flags> getFlags();
}
4.2.3. 高级枚举语法
上述例子都只用到枚举类型的简单语法,枚举主体部分只有逗号隔开的枚举值,事实上枚举类型提供了更强大和更灵活的功能:你能定义枚举的域、方法和构造器。如果定义了一个或更多的构造器,你可以通过枚举值带参数的形式来调用特定的构造器。
尽管枚举不能被继承,但它可以实现一个或多个接口。
更加诡秘的是,每个枚举值都可以定义自已的主体部分来覆写这个枚举类型的方法。但这并不常见,接下来我们看看常见的用法。
4.2.3.1 枚举类型的主体
考虑下面的枚举Prefix, 在它的枚举值后面是主体部分,像常规类一样。它定义了两个域和相应方法。用一个常见的构造器来给域赋值,而每个枚举值都使用这个构造器参数形式来定义。
public enum Prefix {
// These are the values of this enumerated type.
// Each one is followed by constructor arguments in parentheses.
// The values are separated from each other by commas, and the
// list of values is terminated with a semicolon to separate it from
// the class body that follows.
MILLI("m", .001),
CENTI("c", .01),
DECI("d", .1),
DECA("D", 10.0),
HECTA("h", 100.0),
KILO("k", 1000.0); // Note semicolon
// This is the constructor invoked for each value above.
Prefix(String abbrev, double multiplier) {
this.abbrev = abbrev;
this.multiplier = multiplier;
}
// These are the private fields set by the constructor
private String abbrev;
private double multiplier;
// These are accessor methods for the fields. They are instance methods
// of each value of the enumerated type.
public String abbrev() { return abbrev; }
public double multiplier() { return multiplier; }
}
注意:如果枚举值后面还有主体等部分,你需要在最后一个枚举值末尾加分号,否则你可以忽略它或者加逗号。末尾逗号看起来有些怪异,但如果在将来增加了新的枚举值或者重新排列枚举值的顺序时防止错误发生
。
4.2.3.2 实现接口
一个枚举不能声明继承自一个类或枚举类型,但是一个枚举可以实现一个或多个接口。比如说你定义的枚举Prefix具有一个Abbrevable接口中的方法,你可以这样实现:
public interface Abbrevable {
String abbrev();
}
public enum Prefix implements Abbrevable {
// the body of this enum type remains the same as above.
}
4.2.3.3 Value-specific class bodies(不好翻译:枚举值是枚举类型的子类,它可能有主体部分,每一个枚举值都有其相应的类定义段,也作值定类)
除了可以在枚举类型中加主体部分,我们还可以为每一个枚举值提供单独的主体。上例中我演示了在枚举中添加域并用构造器来实例化,这些域可以因枚举值而异。为每个枚举值定义主体的能力说明也可以为它们定义方法——实现了因枚举值而异的行为。当枚举类型反映的是关于表达式解析或者虚拟机上操作码的操作,这种用法一定程度上有用。比如Operator.ADD可能与Operator.SUBTRACT就具有不同的compute()方法。
要定义枚举值主体,只要在紧接着枚举值构造器后面的大括号对中定义,枚举值主体仍然需要逗号隔开,最后一个枚举值主体末尾需要分号,以区分枚举值和该枚举类型的主体。这点很可能忘记。
在编译时每个枚举值主体都产生一个这个枚举类型的匿名子类,而枚举值是它的唯一实例,而枚举值编译时类型是这个枚举类型,非匿名类(因为匿名类无法引用)。因此枚举值主体唯一好处是覆写枚举类型中的方法。如果在枚举值主体中定义了自己域或者方法,不能直接引用它们,只能通过在枚举类型中定义相关的方法才能有用它们。
一种常见的方法是在枚举类型中定义默认的行为,如果枚举值需要非默认的行为,就在枚举值主体中覆写这个方法。另一种有用的变体是在枚举类型中定义一个抽象方法,然后在每个枚举值中具体实现,编译器会强制你在每个枚举值中实现抽象方法。记住:尽管枚举类型有抽象的方法,但它并不是抽象的,也不能被声明abstract,因为枚举值主体实现了抽象方法。
下面是个大例子的摘录,这个例子使用枚举模拟基于栈CPU来描述操作码。这个枚举Opcode定义了一个抽象方法,它在每个枚举值主体中具体实现。这个含有一个构造器枚举类型展示了枚举值的句法:名称、构造参数和匿名主体。首先看枚举类型的域和方法再看枚举值主体,那么这种句法就非常容易理解。
// These are the opcodes that our stack machine can execute.
public enum Opcode {
// Push the single operand onto the stack
PUSH(1) {
public void perform(StackMachine machine, int[] operands) {
machine.push(operands[0]);
}
}, // Remember to separate enum values with commas
// Add the top two values on the stack and push the result
ADD(0) {
public void perform(StackMachine machine, int[] operands) {
machine.push(machine.pop() + machine.pop());
}
},
/* Other opcode values have been omitted for brevity */
// Branch if Equal to Zero
BEZ(1) {
public void perform(StackMachine machine, int[] operands) {
if (machine.top() == 0) machine.setPC(operands[0]);
}
}; // Remember the required semicolon before the class body
// This is the constructor for the type.
Opcode(int numOperands) { this.numOperands = numOperands; }
int numOperands; // how many integer operands does it expect?
// Each opcode constant must implement this abstract method in a
// value-specific class body to perform the operation it represents.
public abstract void perform(StackMachine machine, int[] operands);
}
4.2.3.3.1 什么时候使用value-specific class 主体
当需要对每个枚举值实现独有的特性时value-specific主体独特的语言特性就非常有用。记住:这种用法属于不常用的高级枚举用法,对于低级程序员可能产生混乱。在使用之前首先考虑是否真的必要。在使用这个用法之前,你要确定它设计不过于复杂。首先,检查确实需要行为因枚举值而异,而不是简单的域因枚举值而异。因为因枚举值而异的域可以用构造器来实现,如上面Prefix例中所示。如果覆写枚举类型中的方法,如例中abbrev( ) ,就可能不必要也不合适。
接下来,想想只用简单的枚举类型是否已经足够,如果设计需要复杂的value-specific方法或者枚举值需要许多方法,那么在枚举值主体中定义出来就不太明智,取而代之的是不采用枚举,而是自定义普通类和接口,用单例来实现各个枚举值。如果因枚举值而异的行为在你的枚举中确实需要,那么value-specific 主体就可以考虑。
关于value-specific主体是否够优雅,或者是否容易混乱,人们持有不同意见,一些程序员尽可能地避免它。另一种替代方案是用switch语句来实现这种效果,下面compute( )方法说明了这种用法:
public enum ArithmeticOperator {
// The enumerated values
ADD, SUBTRACT, MULTIPLY, DIVIDE;
// Value-specific behavior using a switch statement
public double compute(double x, double y) {
switch(this) {
case ADD: return x + y;
case SUBTRACT: return x - y;
case MULTIPLY: return x * y;
case DIVIDE: return x / y;
default: throw new AssertionError(this);
}
}
// Test case for using this enum
public static void main(String args[]) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
for(ArithmeticOperator op : ArithmeticOperator.values())
System.out.printf("%f %s %f = %f%n", x, op, y, op.compute(x,y));
}
}
switch方法的缺点是每一次你增加新的枚举值,你都必须修改相应的case语句。并且如果存在有多个方法包含switch语句,造成维护上的麻烦。若忘记了对某个枚举值相关case语句就会造成运行时AssertionError。而通过在value-specific类主体来具体实现枚举类型中的抽象方法很容易将运行时错误提前到编译器检查。要实现value-specific行为,在枚举值主体中方法实现或者在枚举类型中用switch实现性能是差不多的。对枚举值中方法的调用支出和switch语句判断的支出相当。Value-specific 主体增加了类的继承层次,这需要占一定的存储空间和加载时间。
4.2.3.4 枚举类型上的限制
Java对枚举类型代码有许多限制,但很显然这些情况不会在实际中遇到。
当你定义一个枚举类型时编译器在背后做了许多工作:创建一个继承自java.lang.Enum的类,static化声明枚举值,并且产生values() 和valueOf() 方法,如果存在主体,注意不能和自动继承自Enum的成员和方法产生名称冲突。编译器也不允许你显式继承Enum类。
枚举类型实际上是final的,但不能用final声明。但是如果枚举中有value-specific主体部分,编译后的字节码文件不会声明为final。因为枚举类型是final的,所以不能用abstract声明。但可以定义abstract方法,必须在每个枚举值主体部分具体实现继承来的抽象方法(枚举值是这个枚举类型的子类实例),考虑到枚举类型自身是一个完备的整体,所以这种在枚举类型中定义抽象方法的用法并不代表枚举是抽象的(其实认为是抽象也无所谓,关键是我们在枚举项中有具体实现)。
实例化枚举值的构造器受到笼统而模糊的限制:不能使用静态域,原因在于枚举类型或者其他所有类型的类型静态初始化都是自顶向下执行的。枚举值作为静态域在前面声明首先被实例化,因为它们的类型是本枚举类型,所以会调用本类型的构造器和其他的初始化块,这意味着枚举值的初始化执行在本类型的静态块初始化之前,但是由于静态域没有被初始化,所以编译器不允许它们被使用。但如果静态域的值是编译时常量(比如integers和strings)的话,那么编译器能处理,这是唯一的另外。如果在枚举中定义了一个构造器,它不能使用super()调用父类构造器,这是因为编译器自动地在构造器中插入了隐藏名字和序列参数(我不懂这什么意思,参看原文)。如果定义了不止一个构造器,可以使用this()来调用其他的构造器。记住枚举值主体是匿名的类,所以不能有任何的构造器。
4.2.4. The Typesafe Enum Pattern
要更深入地了解enum关键字或者在Java5.0早期的版本中模拟枚举,那么理解 Typesafe Enum Pattern非常有用。这个模式在Joshua Bloch的Effective Java Programming Language Guide (Addison Wesley)书中有描述。这个我们不在细述。
如果你想在早期的Java版本中使用Prefix这样的枚举功能,你可以使用下面的类来模拟枚举,当然这样就不能配合switch语句 、EnumSet 和EnumMap来使用了,编译器也不可能对每个枚举项存在values() 或者valueOf( ) 这样的方法,这样的类也没有枚举类型的序列化支持。因此在你对它实现序列化后必须提供一个readResolve( ) 方法来防止在反序列化是产生多个枚举项的实例。
public final class Prefix {
// These are the self-typed constants
public static final Prefix MILLI = new Prefix("m", .001);
public static final Prefix CENTI = new Prefix("c", .01);
public static final Prefix DECI = new Prefix("d", .1);
public static final Prefix DECA = new Prefix("D", 10.0);
public static final Prefix HECTA = new Prefix("h", 100.0);
public static final Prefix KILO = new Prefix("k", 1000.0);
// Keep the fields private so the instances are immutable
private String name;
private double multiplier;
// The constructor is private so no instances can be created except
// for the ones above.
private Prefix(String name, double multiplier) {
this.name = name;
this.multiplier = multiplier;
}
// These accessor methods are public
public String toString() { return name; }
public double getMultiplier() { return multiplier; }
}
自我总结:枚举是个非常规类!自定义的枚举类型自动继承自Enum类,枚举值的主体部分是本类型的匿名子类,而枚举值是它的唯一实例。枚举值主体主要目的在于实现值定行为,靠覆写枚举类型中的方法(抽象或非抽象)实现。
相关推荐
Java枚举类型(Enum)是Java SE 5.0引入的一种新的数据类型,它为开发者提供了更为强大且安全的方式来表示一组常量。枚举在Java中不仅是一个类,还是一种特殊的类型,允许我们定义自己的常量集合。接下来,我们将...
在Spring Boot项目中,枚举类型(Enums)的使用是一种常见的数据表示方式,它们提供了类型安全和可维护性。本文将深入探讨如何在Spring Boot应用中实现枚举类型的最佳实践,包括前端与后端交互、数据库操作以及序列...
演示如何操作Delphi 的枚举类型。 1. 包含源代码; 2. 包含执行程序 3. 演示如下函数如何使用:GetEnumName、GetEnumProp、GetEnumValue、SetEnumProp 4. 非常简单,一看就会。
然而,易语言本身并不直接支持枚举类型,因此程序员需要通过一些技巧来模拟枚举类型的特性。 模拟枚举类型通常涉及到以下几个方面: 1. 定义枚举值:在易语言中,可以使用常量或全局变量来定义枚举值。例如,我们...
C#中的枚举类型是一种非常实用的数据类型,它允许开发者定义一组命名的常量集合,这些常量通常代表一个特定的数值。通过枚举类型,我们可以将一系列相关的值组织在一起,提高代码的可读性和可维护性。在本文中,我们...
在C语言中,枚举类型不是一种内置类型,而是通过预处理器宏定义实现的,而在C++中,枚举是作为一种真正的类型存在的。本篇文章将详细探讨在VC++ 6.0环境下,枚举类型的定义以及变量声明定义的不同方法。 首先,让...
在编程领域,枚举类型(Enumeration Type)是一种强大的工具,用于定义一组预定义的常量。这些常量通常表示特定的值集合,如颜色、星期、状态等。枚举类型可以提供更清晰、更具可读性的代码,同时也能避免因错误的...
Java中的枚举类型`Enum`是面向对象编程中一种强大的工具,它允许程序员定义自己的常量集合。在Java中,枚举类型不是简单的常量数组,而是一种完整的类,具有类的所有特性,如方法、构造函数和继承。下面将详细探讨`...
"C编译器中枚举类型大小问题" 在不同的C编译器中,枚举类型的大小问题是一个经常被忽视的问题。不同的编译器在处理枚举类型时,可能会出现大小不同的问题。这些问题可能会导致在不同的编译器之间进行代码移植时出现...
在Java编程中,枚举类型(Enum)是一种强大的工具,它可以提供固定的、预定义的值集合,常用于表示有限数量的状态或选项。在关系数据库中,我们可能也需要将这些枚举值存储为列的特定类型。Hibernate,作为Java中...
Java枚举类型是Java语言中的一种特殊的类,用于定义一组固定的常量集合。它在Java中扮演着重要的角色,提供了一种安全、类型化的常量表示方式,比传统的final static变量更具有优势。理解Java枚举类型对于编写高质量...
在Java 5(也被称为Tiger)版本中引入,枚举类型极大地提高了代码的可读性、类型安全性和维护性。在本文中,我们将深入探讨Java枚举的定义、使用方法以及它如何改善传统使用`static final`常量的模式。 首先,让...
枚举类型(Enumeration)在编程语言中是一种特殊的数据类型,用于定义一组有限的常量,这些常量通常代表特定的值或状态。枚举在很多编程语言中都有所支持,如C#、Java、C++和Python等。本文将深入探讨枚举类型的使用...
thinkPHP调用枚举类型,里面根据参数不同返回值不同,初步只封装了input(radio、check)、td、select等。
C++枚举类型的简单实例,设置了enum result{win,lose,tie,cancle} 实现了这四种情况的顺序输出。
首先,我们需要定义一个枚举类型,它包含了所有可能的选择项。例如,假设我们有一个“角色状态”的属性,可以包括"攻击"、"防御"、"移动"和"治疗"等状态: ```csharp public enum CharacterStatus { Attack, ...
### Java枚举类型详解 #### 一、引言 在Java编程语言中,枚举(Enum)作为一种重要的数据类型,在程序设计中扮演着不可或缺的角色。本文将深入探讨Java枚举类型的特性和用法,并通过具体实例说明其优势所在。枚举...
Java枚举类型是Java语言中一种特殊的类,用于定义固定的常量集合,它提供了一种安全、类型化的方式来表示一组有限的值。枚举在Java中被引入为一个完整的类型,不同于C++中的枚举,这使得Java枚举更加强大且易于使用...
在探讨ActionScript 3.0中的枚举类型之前,我们先简单回顾一下枚举类型的基本概念。枚举(Enumeration)是一种特殊的数据类型,用于定义一个有限的、命名的常量集合。这种数据类型通常用于表示一组相关的选项或状态...