在Java中对数组索引使用枚举
在阅读有效的Java时,我遇到了这样一个建议:“使用枚举而不是在Java中对数组索引使用枚举,java,enums,Java,Enums,在阅读有效的Java时,我遇到了这样一个建议:“使用枚举而不是intconstants”。在当前的项目中,我正在做与以下类似的事情: int COL_NAME = 0; int COL_SURNAME = 1; table[COL_NAME] = "JONES" 我将如何使用枚举来实现这一点?由于我不得不使用的接口,我必须使用int作为索引。上面的例子只是一个例子。我实际上使用了一个API,它采用int作为索引值 取决于要求。您可以使用Enum.ordinal()将枚举转换为int 请注意
int
constants”。在当前的项目中,我正在做与以下类似的事情:
int COL_NAME = 0;
int COL_SURNAME = 1;
table[COL_NAME] = "JONES"
我将如何使用枚举来实现这一点?由于我不得不使用的接口,我必须使用
int
作为索引。上面的例子只是一个例子。我实际上使用了一个API,它采用int
作为索引值 取决于要求。您可以使用Enum.ordinal()
将枚举转换为int
请注意,不可能直接将枚举作为索引传递
编辑:
另一种可能是使用
Map映射
,然后使用Map.get(EnumValue)
将一个有用的模式与反模式一起应用通常会失败;-)
在您的例子中,当您想用enum
值替换int
常量时,将数组用于与数组不完全相似的数据会出现问题
一个干净的(er)解决方案类似于一个使用enum
值作为键的
或者,如果绝对必要,您也可以使用
如果某些API强制您传递
int
值,但您可以控制实际值(即,您可以传递自己的常量),那么您可以切换到在代码中使用enum
值,并仅在代码与API接口的位置转换为/从enum
。enumValue.ordinal()
的反向操作是EnumClass.values()[ordinal]
)。听起来您好像在尝试使用EnumMap。这是一个包含值数组的映射
enum Column {
NAME, SURNAME
}
Map<Column, String> table = new EnumMap<Column, String>(Column.class);
table.put(Column.NAME, "JONES");
String name = table.get(Column.NAME);
由于您必须使用该表,因此无法实际使用
EnumMap
,因此我个人认为最好的解决方案是坚持使用您所拥有的。在枚举中,元素的序数值不应具有任何内在含义,而在您的示例中,它们具有内在含义,因为它们被用作表中的索引
问题不在于您没有使用枚举,而在于您需要神奇的值来从表中提取列数据。在这种情况下,使用整型常量是作业的正确工具,除非您能够解决该表的潜在问题
现在,您可以通过将表包装到访问它的类中,并在该类中使用枚举来解决这个问题。但是这引入了更多的代码,另一层间接寻址,实际上并不能为您解决任何问题,除了一个枚举比一个int值列表更容易维护之外(由于您必须维护您现在编写的包装器,这一点被大大抵消了)
如果你正在编写一个其他人会使用的公共API,你可以考虑这项工作,因为它会避免依赖于一些随时间变化的魔法值(紧密耦合会破坏事物)。如果您是,那么在内部使用EnumMap
的包装器可能是一个不错的选择
<>否则,就这样。我也遇到了这个问题,并且来自C++世界,我不希望遇到这个问题。 enum的美妙之处在于,它可以创建一系列具有唯一值的相关常量,而实际值与此无关。它们的使用使代码更易于阅读,并防止变量被设置为无效的枚举值(特别是在Java中),但在这种情况下,这是一个很大的难题。虽然您可能有“enum宠物{CAT,BIRD,DOG}”,并不真正关心CAT,BIRD,DOG实际代表什么价值,但它写得非常漂亮和干净: 我的宠物[猫]=“德克斯特”; 我的宠物[鸟]=“波利”; 我的宠物[狗]=“Boo Rooh” 在我的情况下,我最终编写了一个转换函数,其中传入一个枚举值,然后返回一个常量。我讨厌满怀激情地做这件事,但这是我所知道的维护enum的方便性和错误检查的唯一干净方法
private int getPetsValue(Pets inPet) {
int value = 0;
switch (inPet) {
case CAT: value = 0; break;
case BIRD: value = 1; break;
case DOG: value = 2; break;
default:
assert(false);
value = 0;
break;
}
return value;
}
根据数组的值,您可能会转而查看对象。例如,如果您的数组如下所示
person[FIRST_NAME] = "Jim Bob"
person[SURNAME] = "Jones"
person[ADDRESS] = "123 ABC St"
person[CITY] = "Pleasantville"
...
Person jimBob = new Person("Jim Bob", "Jones");
jimBob.setAddress("123 ABC St", "Pleasantville", "SC");
....
那么你真正想要的是这样的东西
person[FIRST_NAME] = "Jim Bob"
person[SURNAME] = "Jones"
person[ADDRESS] = "123 ABC St"
person[CITY] = "Pleasantville"
...
Person jimBob = new Person("Jim Bob", "Jones");
jimBob.setAddress("123 ABC St", "Pleasantville", "SC");
....
请参见您可以使用如下构造函数定义
enum
:
public enum ArrayIndex {
COL_NAME(0), COL_SURNAME(1);
private int index;
private ArrayIndex(int index) {
this.index = index;
}
public int getIndex() {
return this.index;
}
};
然后像这样使用它:
public static void main (String args[]) {
System.out.println("index of COL_NAME is " + ArrayIndex.COL_NAME.getIndex());
}
我相信表[COL_NAM.ordinal()]是EnumMap在幕后所做的,只是比我们中的一个人可能在动态中所写的更正确。@ILMTitan:我同意。我刚刚发布了这个,因为OP说一些API强迫他使用数组。我不同意这是一个反模式。其他语言确实将枚举视为原语,在枚举基础上设置范围、子范围和数组非常有意义。它比需要声明
静态final int。。。SOMETHING
和write选择(…){..}
语句imho。其次,我们需要一个EnumMap
这一事实是缺少某些东西的初步证据。@威尔:它所能证明的就是Java中的枚举与其他语言中的枚举不同。在其他语言中,它们是美化的整数,并被正确地这样对待。在Java中,它们不是。盲目地应用其他语言的模式可能是一种反模式。我同意这一点,它们可能被错误地命名为某些文档:。虽然有人真的应该研究PL/1和ALGOL-68示例。我不确定你在做什么,但看起来你不知道Enum.ordinal()
。嗯,你最好不要像java一样尝试程序C++,它是相似但不同的,盲目地应用你所习惯的一切是灾难的一种方式。