在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 请注意

在阅读有效的Java时,我遇到了这样一个建议:“使用枚举而不是
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++,它是相似但不同的,盲目地应用你所习惯的一切是灾难的一种方式。