2013-01-04 43 views
14

我有了一个枚举属性的实体:使用枚举在开关/箱

// 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值!我不能使用如下的开关:

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

我该怎么办?

+0

可能是多数民众赞成在最坏的情况下,但唯一的解决办法是我可以使用一个不同的getter通过扩展类,返回值作为枚举。 –

回答

26

你可以提供在枚举了一个静态方法:

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的可能使用的顺序属性,但是该实现细节现在被包含在枚举类中。

11

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

然后,您可以通过有序的枚举,你可以这样做:

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

...那么你可以用枚举做你的开关......

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

“,因此您不需要手动指定int ...”<---当您需要与其他(第三方)软件或具有固定整数的机器进行通信时,这不是真的界面(例如消息类型)! – user504342

+0

@ user504342:这个答案的重点在于枚举已经包含一个序号,所以如果你的用例允许你依赖that_,你可以不需要做更多的事情。如果因为必须符合某些现有方案而无法使用序号,那么[assylias的答案](http://stackoverflow.com/a/14154869/1212960)涵盖了这一点。 –

+0

\ @GregKopff:抱歉不同意。根据Joshua Bloch的书籍Effective Java(2nd ed。),你不应该依赖序数值。请参阅第31项,其中明确指出:“永远不要从枚举的枚举中获取与其相关的值;将其存储在实例字段中”。这本书详细解释了这是为什么。 – user504342