在switch/case语句中使用枚举

17

我有一个实体,其中包含一个枚举类型的属性:

// MyFile.java
public class MyFile {   
    private DownloadStatus downloadStatus;
    // other properties, setters and getters
}

// DownloadStatus.java
public enum DownloadStatus {
    NOT_DOWNLOADED(1),
    DOWNLOAD_IN_PROGRESS(2),
    DOWNLOADED(3);

    private int value;
    private DownloadStatus(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
} 

我想将这个实体保存在数据库中并检索它。问题是,我将int值保存在数据库中,而我得到的是int值!我不能像下面这样使用switch:

MyFile file = new MyFile();
int downloadStatus = ...
switch(downloadStatus) {
    case NOT_DOWNLOADED:
    file.setDownloadStatus(NOT_DOWNLOADED);
    break;
    // ...
}    

我该怎么办?


也许这是最糟糕的情况,但我能想到的唯一解决方案是通过扩展类使用不同的getter返回枚举值。 - ManMohan Vyas
2个回答

29
您可以在枚举中提供一个静态方法:
public static DownloadStatus getStatusFromInt(int status) {
    //here return the appropriate enum constant
}

然后在您的主要代码中:

int downloadStatus = ...;
DowloadStatus status = DowloadStatus.getStatusFromInt(downloadStatus);
switch (status) {
    case DowloadStatus.NOT_DOWNLOADED:
       //etc.
}
与普通方法相比,这种方法的优点在于如果你的枚举类型发生了改变,它仍然可以正常工作,例如:
public enum DownloadStatus {
    NOT_DOWNLOADED(1),
    DOWNLOAD_IN_PROGRESS(2),
    DOWNLOADED(4);           /// Ooops, database changed, it is not 3 any more
}

请注意,getStatusFromInt 的初始实现可能使用序数属性,但该实现细节现在已封装在枚举类中。


12

每个Java枚举都有一个自动分配的序数,因此您不需要手动指定int(但请注意,序数从0开始而不是1)。

然后,要从序数获取枚举,可以执行以下操作:

int downloadStatus = ...
DownloadStatus ds = DownloadStatus.values()[downloadStatus];

...然后您可以使用枚举来执行切换操作...

switch (ds)
{
  case NOT_DOWNLOADED:
  ...
}

1
“...所以你不需要手动指定int。”<---但是当您需要与具有某个接口的固定整数的其他(第三方)软件或机器进行通信(例如消息类型)时,这是不正确的!请注意。 - user504342
@user504342:这个答案的重点是枚举已经包含了一个序数,所以_如果您的用例允许您依赖它_,您可以不需要做任何其他事情。如果您不能使用序数,因为您必须符合某些现有方案,则assylias' answer涵盖了此内容。 - Greg Kopff
1
抱歉不同意。根据Joshua Bloch的书《Effective Java》(第二版),你不应该依赖于序数值。请参见第31条,其中明确指出:“永远不要从其序数派生与枚举相关联的值;而是将其存储在实例字段中。”该书详细解释了为什么这样做。 - user504342

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接